Saltar para o conteúdo
Last updated

Implantação de servidor Linux

Implante o MoreLogin em um servidor Ubuntu headless e automatize perfis de navegador pela Local API — sem ambiente gráfico.


O que você alcançará

Ao final deste guia você terá:

  1. A running MoreLogin instance on an Ubuntu 24.04 headless server
  2. Encaminhamento de rede configurado para que máquinas externas possam conectar via CDP (Chrome DevTools Protocol)
  3. Um script de automação Python funcional que cria, inicia, controla e limpa perfis de navegador

Visão geral da arquitetura

┌──────────────────────────────────────────────────────────┐
│                    Ubuntu 24.04 Server                   │
│                                                          │
│  ┌──────────────┐    ┌───────────────────────────────┐   │
│  │   xvfb       │───▶│  MoreLogin AppImage           │   │
│  │ (virtual     │    │  Local API :40000             │   │
│  │  display)    │    │  CDP debug :<dynamic>         │   │
│  │              │    │    (127.0.0.1, per profile)   │   │
│  └──────────────┘    └───────────────────────────────┘   │
│                              │                           │
│                        socat forwarding                  │
│                              │                           │
│                     0.0.0.0:40001 → 127.0.0.1:40000      │
│                     0.0.0.0:<N+1> → 127.0.0.1:<N>        │
└──────────────────────────────────────────────────────────┘

                          External machine
                     (Playwright / Puppeteer / Selenium)

[!NOTE] A porta de depuração CDP é dinâmica — cada perfil de navegador recebe a sua própria porta, retornada pela resposta de /api/env/start.


Pré-requisitos

RequisitoDetalhes
Sistema operacionalUbuntu 24.04 Server (x86_64)
Especificações recomendadas8 vCPU, 8 GB RAM (supports ~5 concurrent profiles)
RedeAcesso de saída à Internet; open inbound port 40001 and the forwarded CDP ports you choose, or use SSH tunnels instead
Python (opcional)Python 3.8+ with pip for running the example script

Passo 1 — Instalar dependências do sistema

Conecte-se ao servidor por SSH e instale os pacotes necessários:

# FUSE support (required for AppImage)
sudo apt install -y libfuse2t64

# GTK / accessibility / display libraries
sudo apt install -y libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0
sudo apt install -y libcups2
sudo apt install -y libgtk-3-0 libgdk-pixbuf2.0-0
sudo apt install -y libgbm1 libxkbcommon0 libasound2t64

# Virtual framebuffer (headless display)
sudo apt install -y xvfb

# TCP forwarder
sudo apt install -y socat

Instalar fontes (opcional)

Se as páginas do navegador aparecerem sem texto ou com caracteres faltando, instale os pacotes de fontes correspondentes:

# CJK (Chinese, Japanese, Korean)
sudo apt install -y fonts-noto-cjk fonts-noto-cjk-extra

# Arabic
sudo apt install -y fonts-noto-color-emoji fonts-noto-extra

Para outros idiomas, instale o pacote correspondente da família de fontes Noto.


Passo 2 — Baixe e inicie maisLogin

2.1 Baixe o AppImage

wget https://get.morelogin.com/client/prod/linux/x64/2.54.0/MoreLogin_x86_64_2.54.0.AppImage
chmod +x MoreLogin_x86_64_2.54.0.AppImage

Substitua 2.54.0 pela versão mais recente disponível na sua conta MoreLogin ou na página de download.

2.2 Iniciar mais Login em segundo plano

Use xvfb-run para fornecer um display virtual e então execute o AppImage:

nohup xvfb-run -a ./MoreLogin_x86_64_2.54.0.AppImage --no-sandbox > morelogin.log 2>&1 &

Verifique se foi iniciado com sucesso:

# Check the process is running
ps aux | grep MoreLogin

O processo pode levar de 5 a 10 segundos para inicializar por completo.


Step 3 — Log In to MoreLogin via API (Required)

[!CAUTION] Você deve fazer login antes de chamar qualquer outro endpoint da API local. Em um servidor headless, não há GUI para fazer login manualmente, portanto, você deve autenticar por meio da API. Sem esta etapa, todas as chamadas de API retornarão:

{"status": "error", "code": 401, "message": "Your login status has expired, please log in again"}

3.1 Obtenha suas credenciais de API

Abra o cliente desktop do MoreLogin (em qualquer máquina onde você esteja conectado) e vá em Configurações → API e MCP.

Configurações de API do MoreLogin — copie o APP ID e a API Key na seção Open API

3.2 Faça login via curl

Chame o endpoint de login com suas credenciais:

curl -X POST http://127.0.0.1:40000/api/user/login \
  -H "Content-Type: application/json" \
  -d '{
    "apiId": "YOUR_APP_ID",
    "apiKey": "YOUR_API_KEY"
  }'

Uma resposta bem-sucedida é semelhante a:

{"code": 0, "msg": null, "data": true}

3.3 Verifique o login

Confirme que a API está pronta listando os perfis de navegador:

curl -s -X POST http://127.0.0.1:40000/api/env/page \
  -H "Content-Type: application/json" \
  -d '{"pageNo": 1, "pageSize": 1}'

Uma resposta {"code":0, ...} significa que você está autenticado e a API está pronta.

Ponto de verificação: seu servidor MoreLogin está totalmente operacional. Siga para o Passo 4.

[!NOTE] A sessão de login persiste enquanto o processo do MoreLogin estiver em execução. Se você reiniciar o AppImage, precisará autenticar novamente.


Passo 4 — Configurar o encaminhamento de rede (socat)

Por padrão, tanto a Local API (:40000) quanto as portas de depuração CDP escutam em 127.0.0.1. Se você precisa acessá-las de fora, encaminhe as portas.

[!WARNING] Risco de segurança — não exponha essas portas à internet pública.

  • A Local API não tem autenticação embutida na maioria dos endpoints.
  • Uma porta de depuração CDP concede controle remoto total da instância do navegador (ler cookies, injetar scripts, capturar tela).

Recomendações:

  • Use um túnel SSH em vez do socat para acesso remoto: ssh -L 40000:127.0.0.1:40000 user@server
  • Se precisar usar o socat, restrinja o acesso com regras de firewall a IPs específicos apenas
  • Use uma VPN ou grupos de segurança do provedor de nuvem para limitar o tráfego de entrada
  • Nunca abra as portas 40001 / portas CDP para 0.0.0.0 em um servidor exposto à internet sem restrição de IP

4.1 Encaminhar a porta API local

nohup socat TCP-LISTEN:40001,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:40000 &

Máquinas externas agora podem alcançar a API em http://<server-ip>:40001.

4.2 Portas de depuração CDP de encaminhamento

When you start a browser profile via the API, the response includes a dynamic debugPort (e.g., 9222). Cada perfil pode receber uma porta diferente. Forward it so external automation tools (Playwright, Puppeteer, Selenium) can connect:

# Example: if debugPort=9222, forward to external port 9223 (debugPort + 1)
# Adjust both ports to match the actual debugPort returned by /api/env/start
nohup socat TCP-LISTEN:9223,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:9222 &

[!WARNING] Ao executar vários perfis simultaneamente, garanta que as portas encaminhadas não colidam com as portas de depuração de outros perfis.

[!TIP] Em produção, crie o encaminhamento socat dinamicamente após cada chamada de /api/env/start, usando o debugPort retornado.

Se os scripts de automação rodam no mesmo servidor, você pode dispensar o socat e conectar direto em 127.0.0.1.

4.3 Abrir portas de firewall

Se você usar o socat, restrinja o acesso apenas a IPs confiáveis:

# Allow only a specific IP (recommended)
sudo ufw allow from <YOUR_IP> to any port 40001 proto tcp
sudo ufw allow from <YOUR_IP> to any port 9223 proto tcp

# Or allow from any IP (NOT recommended for production)
# sudo ufw allow 40001/tcp
# sudo ufw allow 9223/tcp

4.4 Recomendado: use o túnel SSH

Para o acesso remoto mais seguro, use um túnel SSH — sem mudanças de firewall nem socat.

Como a porta CDP é dinâmica (atribuída quando você inicia um perfil), o fluxo é:

  1. Túnel a porta da API primeiro:

    # Run this on your local machine
    ssh -L 40000:127.0.0.1:40000 user@<server-ip>
  2. Inicie o perfil pela API tunelada (http://127.0.0.1:40000/api/env/start) e leia o debugPort retornado.

  3. Abra um segundo túnel para a porta CDP:

    # Replace <debugPort> with the actual port returned by the API
    ssh -L <debugPort>:127.0.0.1:<debugPort> user@<server-ip>
  4. Conecte em http://127.0.0.1:<debugPort> a partir dos seus scripts Playwright / Puppeteer, como se o servidor fosse local.

[!TIP] Você pode combinar os dois túneis em um único comando se souber a faixa de portas com antecedência, por exemplo:

ssh -L 40000:127.0.0.1:40000 -L 9222:127.0.0.1:9222 -L 9223:127.0.0.1:9223 user@<server-ip>

Mas na prática é mais fácil abrir primeiro o túnel da API e depois adicionar túneis por perfil conforme necessário.


Passo 5 — Exemplo de automação rápida

Abaixo está um exemplo mínimo em Python mostrando o ciclo de vida completo de um perfil de navegador. Para o script de produção completo, veja o repositório de demos.

5.1 Instalar dependências do Python

pip install requests playwright

O Playwright é usado aqui apenas pelo seu cliente CDP (connect_over_cdp). Você não precisa executar playwright install.

5.2 Definir --no-sandbox para Perfis de Navegador (Obrigatório no Linux)

No Linux Server, o mecanismo do navegador deve ser executado com a flag --no-sandbox. Você passa este parâmetro através do campo startupParams ao criar ou atualizar um perfil de navegador.

[!CAUTION] Sem --no-sandbox, o navegador não conseguirá iniciar na maioria dos ambientes de servidor Linux (especialmente ao executar como root ou sem uma sessão de desktop completa).

Novos perfis — incluir startupParams na criação

Use /api/env/create/advanced para criar um perfil com startupParams (o endpoint /api/env/create/quick não suporta este campo):

curl -X POST http://127.0.0.1:40000/api/env/create/advanced \
  -H "Content-Type: application/json" \
  -d '{
    "browserTypeId": 1,
    "operatorSystemId": 5,
    "startupParams": ["--no-sandbox"]
  }'

[!TIP] Se você usou /api/env/create/quick para criar o perfil, chame /api/env/update para adicionar --no-sandbox antes de iniciar — veja abaixo.

Perfis existentes — atualizar via /api/env/update

Se você já possui perfis de navegador criados sem --no-sandbox, atualize-os antes de iniciar:

curl -X POST http://127.0.0.1:40000/api/env/update \
  -H "Content-Type: application/json" \
  -d '{
    "envId": "YOUR_ENV_ID",
    "startupParams": ["--no-sandbox"]
  }'

[!NOTE] O campo startupParams aceita um array de strings. Você também pode incluir outras flags do Chrome (por exemplo, ["--no-sandbox", "--disable-gpu"]). A flag --no-sandbox é necessária apenas no Linux — perfis Windows e macOS não precisam dela.


5.3 Criar → Iniciar → Automatizar → Limpeza

Este exemplo pressupõe que o script roda no mesmo servidor que o MoreLogin. Para cenários remotos, veja as observações abaixo.

import requests
from playwright.sync_api import sync_playwright

# ── Configuration ──────────────────────────────────────────
# Local:  script runs on the SAME server as MoreLogin
# Remote: script runs on a DIFFERENT machine — see notes below
API_BASE  = "http://127.0.0.1:40000"


# ① Create a browser profile
resp = requests.post(f"{API_BASE}/api/env/create/quick", json={
    "browserTypeId": 1,
    "operatorSystemId": 5,
    "quantity": 1
})
resp_data = resp.json()
assert resp_data["code"] == 0, f"Create failed: {resp_data}"
env_id = resp_data["data"]["envIds"][0]
print(f"✅ Created profile: {env_id}")


# ①-b Add --no-sandbox (required on Linux Server)
resp = requests.post(f"{API_BASE}/api/env/update", json={
    "envId": env_id,
    "startupParams": ["--no-sandbox"]
})
resp_data = resp.json()
assert resp_data["code"] == 0, f"Update failed: {resp_data}"
print(f"✅ Set --no-sandbox for profile: {env_id}")


# ② Start the profile (headless)
resp = requests.post(f"{API_BASE}/api/env/start", json={
    "envId": env_id
})
resp_data = resp.json()
assert resp_data["code"] == 0, f"Start failed: {resp_data}"
debug_port = resp_data["data"]["debugPort"]   # Dynamic — different for each profile
print(f"✅ Started — debug port: {debug_port}")


# ③ Build the CDP URL
cdp_url = f"http://127.0.0.1:{debug_port}"


# ④ Connect via CDP and automate
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(cdp_url)
    page = browser.contexts[0].pages[0]
    page.goto("https://www.google.com")
    page.screenshot(path=f"screenshot_{env_id}.png")
    print(f"✅ Screenshot saved")
    # Use disconnect() — not close() — to detach without killing the browser.
    # The profile will be stopped cleanly via the API in step ⑤.
    browser.disconnect()


# ⑤ Stop the profile
requests.post(f"{API_BASE}/api/env/close", json={"envId": env_id})
print(f"✅ Profile stopped")


# ⑥ Delete the profile
requests.post(f"{API_BASE}/api/env/remove", json={"envIds": [env_id]})
print(f"✅ Profile deleted")

[!NOTE] Running from a remote machine? Two approaches:

Opção A — túnel SSH (recomendado): Configure túneis SSH da sua máquina local para o servidor (consulte § 4.4) e mantenha API_BASE = "http://127.0.0.1:40000" e cdp_url = f"http://127.0.0.1:{debug_port}" — o SSH faz com que as portas remotas pareçam locais.

Opção B — socat no servidor: No servidor, inicie o encaminhamento socat para a porta da API e para cada porta CDP:

# Execute isto no SERVIDOR, não na sua máquina local
socat TCP-LISTEN:40001,fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:40000 &
socat TCP-LISTEN:$((debug_port+1)),fork,reuseaddr,bind=0.0.0.0 TCP:127.0.0.1:$debug_port &

Then in your script, set API_BASE = "http://<server-ip>:40001" and cdp_url = f"http://<server-ip>:{debug_port + 1}". ⚠️ Restrinja o acesso com regras de firewall — veja § 4.3.

[!IMPORTANT] The resp.json()["data"]["envIds"] structure matches the current /api/env/create/quick response format. Se você encontrar um formato diferente (por exemplo, data: ["id1", ...]), verifique a Referência da API da sua versão. Os formatos de resposta podem variar entre as versões.


Referência de desempenho

Os resultados a seguir foram obtidos em uma VM Ubuntu 24.04 Server (8 vCPU, 8 GB de RAM) usando o script completo de teste de estresse.

MétricaValor
Total de corridas100
Simultaneidade4 (simultâneo)
Taxa de sucesso100,0%
Tempo total604,06s
Tempo médio por tarefa6,04s
Rendimento0,17 tarefas/s

Esses números servem como base. Actual performance depends on server specs, network conditions, and page complexity.


Implantação de produção (systemd)

Em servidores de produção, execute o MoreLogin como um serviço systemd para ter inicialização automática no boot e reinício em caso de falha.

Crie o arquivo de serviço

sudo tee /etc/systemd/system/morelogin.service > /dev/null <<'EOF'
[Unit]
Description=MoreLogin Browser (headless)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/morelogin
ExecStart=/usr/bin/xvfb-run -a /opt/morelogin/MoreLogin_x86_64_2.54.0.AppImage --no-sandbox
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

Ajuste os caminhos de WorkingDirectory e ExecStart para onde você colocou o AppImage.

[!TIP] Para produção, considere criar um usuário dedicado (por exemplo, morelogin) em vez de executar como root e ajuste a propriedade e as permissões do arquivo de acordo. Se o AppImage atualmente exigir privilégios de root, você poderá manter User=root, mas isolar o processo em uma conta não root é uma prática recomendada.

Habilitar e iniciar

sudo systemctl daemon-reload
sudo systemctl enable morelogin    # Auto-start on boot
sudo systemctl start morelogin     # Start now

Gerenciar o serviço

sudo systemctl status morelogin    # Check status
sudo journalctl -u morelogin -f    # Stream logs
sudo systemctl restart morelogin   # Restart
sudo systemctl stop morelogin      # Stop

[!NOTE] Após um reinício, você precisa chamar o endpoint de login novamente — a sessão da API não sobrevive ao reinício.


Solução de problemas

MoreLogin não inicia

AppImages require FUSE to run.

Correção: Instale o suporte FUSE:

sudo apt install -y libfuse2t64

Páginas do navegador aparecem sem texto / com caracteres faltando

Correção: instale o pacote de fontes do idioma desejado (veja Passo 1 — Instalar fontes).

Conexão CDP recusada pela máquina externa

Cause: CDP debug ports bind to 127.0.0.1 by default.

Correção: configure o encaminhamento socat (veja Passo 4) e garanta que o firewall permita a porta.

curl to Local API returns "Connection refused"

Causa: o MoreLogin ainda não terminou de iniciar, ou o processo travou.

Correção:

  1. Aguarde 5 a 10 segundos após a inicialização
  2. Verifique se há erros no morelogin.log
  3. Verifique se o processo está em execução: ps aux | grep MoreLogin

API retorna 401 “status de login expirou”

{"status": "error", "code": 401, "message": "Your login status has expired, please log in again"}

Causa: você não fez login pela API, ou o processo do MoreLogin foi reiniciado.

Correção: chame o endpoint de login antes de qualquer outra chamada de API (veja Passo 3).


Próximas etapas

ObjetivoLigação
Referência completa da API do navegadorAPI do navegador
Configuração de autenticaçãoGuia de autenticação
Exemplos de dramaturgo / selênio / titereiroExemplos de automação
Script completo de teste de estresse do LinuxGitHub — linux_server_test.py
Início rápido da CLIGuia CLI