SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-24

Por que o n8n fica offline no seu VPS

O aviso pode ser websocket, loop de restart, OOM kill ou agenda parada. Veja como distinguir cada falha no Docker, Node.js e reverse proxy.

Por que o n8n fica offline: quatro falhas, um sintoma

“o n8n fica offline” é uma frase que pode descrever quatro falhas diferentes, e cada uma exige uma correção diferente. O editor mostra um aviso de ligação perdida enquanto o contentor continua a funcionar normalmente. O contentor reinicia sozinho. O kernel termina o processo Node.js por utilizar demasiada memória. Ou não existe qualquer problema com o processo, e um workflow ativo simplesmente nunca é executado. Se alterar a definição errada, passará um fim de semana a investigar um problema que nunca existiu.

Por isso, descubra qual é a falha antes de alterar qualquer configuração. O n8n é executado como um único processo Node.js, normalmente dentro de um contentor Docker, atrás de um reverse proxy que termina o TLS (transport layer security). Cada uma dessas camadas falha de forma diferente, mas o browser apresenta a mesma mensagem para todas elas.

Diagnostique nesta ordem

Execute estes comandos no VPS (virtual private server) e leia os valores apresentados pela sua própria máquina. Não os compare com números de uma publicação num fórum. Os valores relevantes aqui descrevem o seu servidor, não o de outra pessoa.

docker ps -a --filter name=n8n
docker logs --tail 200 --timestamps n8n
docker inspect n8n | grep -iE 'Status|Running|RestartCount|OOMKilled|ExitCode'
docker stats --no-stream

A coluna STATUS de docker ps -a indica há quanto tempo o contentor está no estado atual. Compare esse valor com o momento em que o problema começou. Se o contentor estiver ativo desde muito antes de o banner aparecer, o n8n nunca ficou indisponível. O que falhou foi a ligação entre o browser e o backend. O caminho websocket correspondente é explicado na secção seguinte.

RestartCount indica quantas vezes o Docker reiniciou este contentor. Anote o número, aguarde um minuto e leia-o novamente. Se o número aumentar enquanto observa, existe um ciclo de reinício. As linhas do log imediatamente anteriores a cada reinício indicam a causa.

OOMKilled é um sinalizador com valor true ou false. True significa que o kernel Linux terminou o processo porque este ultrapassou um limite de memória, seja o limite do próprio contentor ou o da máquina inteira. Esse campo distingue um encerramento por falta de memória de qualquer outro tipo de saída. Por isso, leia-o antes de avançar para suposições.

ExitCode indica o código com que o contentor terminou da última vez. Não precisa de memorizar o significado de cada código. Leia o seu valor e, em seguida, leia o final de docker logs correspondente ao mesmo momento. O final do log e o sinalizador de falta de memória, em conjunto, indicam o que aconteceu. Isoladamente, qualquer um deles pode induzir em erro.

docker stats apresenta a utilização atual de memória junto ao limite em vigor. Deixe este comando em execução num segundo terminal, execute o workflow que causa o problema e observe o comportamento do valor enquanto a falha ocorre.


O banner de perda de ligação normalmente é causado pelo reverse proxy

O editor do n8n mantém uma ligação push de longa duração aberta com o backend para transmitir o progresso da execução para a tela. Por padrão, essa ligação é um WebSocket, selecionado por N8N_PUSH_BACKEND, e o valor padrão é websocket. Um WebSocket começa como um pedido HTTP normal que contém os cabeçalhos Connection: Upgrade e Upgrade: websocket. O servidor responde 101 Switching Protocols e, a partir desse momento, os dois lados utilizam o mesmo socket TCP nos dois sentidos.

Duas situações interrompem esse funcionamento, e ambas ocorrem no proxy, não no n8n. O proxy comunica com o upstream usando HTTP/1.0 ou remove os cabeçalhos de upgrade. Nesse caso, o upgrade nunca ocorre e o editor tenta restabelecer a ligação continuamente. Ou o upgrade é concluído, mas o proxy fecha o socket mais tarde por falta de atividade, porque um WebSocket sem mensagens tem exatamente o aspeto de uma ligação inativa. Nos dois casos, o contentor está saudável. O banner indica que o browser perdeu o canal.

Confirme isto no browser antes de editar qualquer configuração. Abra as ferramentas de desenvolvimento, aceda ao separador Network, filtre por WS e recarregue o editor. O pedido push deve chegar a 101 Switching Protocols e permanecer aberto. Um pedido push que devolve um código de estado normal ou que reaparece a cada poucos segundos aponta para o proxy.

Configurações do nginx que mantêm o editor conectado

O nginx não encaminha uma atualização sem que isso seja configurado. proxy_pass usa HTTP/1.0 para comunicar com o backend por predefinição, e Connection e Upgrade são cabeçalhos hop-by-hop que o nginx remove durante o encaminhamento. É necessário repor ambos. O bloco map deve ficar no contexto http, e não dentro de server. Se o restante do bloco de servidor abaixo não for familiar, o guia linha a linha de um bloco de servidor do nginx explica o que cada diretiva faz.

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
server {
    listen 443 ssl;
    http2 on;
    server_name n8n.example.com;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
    }
}

proxy_read_timeout é a linha que costuma ficar de fora. O valor predefinido é 60 segundos e também se aplica a um WebSocket atualizado. Por isso, um separador do editor deixado aberto numa instância sem atividade perde a ligação cerca de um minuto depois da última mensagem passar por ele. Aumentar este valor corrige o banner que aparece quando regressa a um separador deixado aberto.

sudo nginx -t && sudo systemctl reload nginx
sudo nginx -T | grep -iE 'proxy_http_version|upgrade|proxy_read_timeout'

nginx -T apresenta toda a configuração em execução, em vez de apenas um ficheiro. Assim, confirma que a alteração foi efetivamente carregada. Se nenhum ficheiro incluído por uma linha include contiver a configuração, uma correção correta parecerá não fazer nada.

Depois, informe o n8n de que está atrás de um proxy, porque ele cria URLs com base nestes valores.

environment:
  - N8N_HOST=n8n.example.com
  - N8N_PROTOCOL=https
  - N8N_PORT=5678
  - N8N_PROXY_HOPS=1
  - N8N_WEBHOOK_URL=https://n8n.example.com/

N8N_PROXY_HOPS tem o valor predefinido 0. Isso faz com que o n8n trate o endereço de ligação como o endereço do cliente e ignore X-Forwarded-For. Defina-o como o número de proxies à frente do contentor. Em agosto de 2026, N8N_WEBHOOK_URL é o nome atual, e o nome antigo WEBHOOK_URL continua a funcionar, embora apresente um aviso de descontinuação no arranque.

O Traefik encaminha WebSockets, mas termina a ligação por timeout

O Traefik encaminha uma atualização para WebSocket sem middleware nem labels adicionais. Por isso, quando um utilizador do Traefik vê este banner, normalmente está a atingir um timeout, e não a lidar com um cabeçalho em falta. Os parâmetros estão no entryPoint. Em agosto de 2026, no Traefik v3, idleTimeout tem o valor predefinido de 180 segundos e readTimeout tem o valor predefinido de 60 segundos.

entryPoints:
  websecure:
    address: ":443"
    transport:
      respondingTimeouts:
        readTimeout: 0
        idleTimeout: 3600s

O Caddy trata automaticamente da atualização em reverse_proxy e não precisa de nenhuma diretiva para isso. Se não puder alterar o proxy porque outra pessoa o administra, altere o canal de push com N8N_PUSH_BACKEND=sse. Os SSE (server-sent events) são uma resposta HTTP normal mantida aberta. Por isso, funcionam através de um proxy que recusa atualizações, embora um timeout de inatividade agressivo também possa interrompê-los. Escolher o próprio proxy é uma decisão separada. A comparação entre nginx, Caddy e Traefik explica o custo operacional de cada opção.

Quando o container está realmente a reiniciar

Se RestartCount aumentar, o container está a falhar e o Docker está a iniciá-lo novamente. Compare os timestamps dos logs com cada reinício e leia o que aconteceu imediatamente antes. Quatro causas abrangem quase todos os casos: um erro de configuração que impede o arranque, uma base de dados à qual o n8n não consegue aceder, uma falha depois de o processo arrancar e uma terminação por falta de memória.

Comece pelo volume, porque as permissões são a causa menos evidente. A imagem oficial é executada com o utilizador sem privilégios node e guarda os dados em /home/node/.n8n. Um bind mount criado por root não pode ser escrito por esse utilizador. Por isso, o processo termina no arranque todas as vezes, e a política de reinício oculta o problema num ciclo.

docker compose config
docker run --rm -it --entrypoint sh docker.n8n.io/n8nio/n8n -c 'id'
docker exec n8n ls -ld /home/node/.n8n

Um volume nomeado evita completamente o problema, porque o Docker cria-o com o proprietário correto. Se precisar de um bind mount, chown o diretório do host para o ID numérico de utilizador apresentado pelo primeiro comando. Vale a pena compreender uma vez o mapeamento de proprietários entre o host e o container. O guia sobre PUID e PGID explica como estas imagens determinam quem pode escrever nos ficheiros.

O encerramento por falta de memória que parece uma falha

Existem dois limites de memória independentes acima de um processo n8n, e cada um falha de forma diferente. O limite do grupo de controlo do contentor é aplicado pelo kernel: quando é ultrapassado, o processo é encerrado imediatamente, sem possibilidade de escrever qualquer informação, e OOMKilled devolve true. O limite do heap do V8 é aplicado dentro do Node.js: quando é ultrapassado, o Node gera um erro de heap com um stack trace e termina por iniciativa própria, pelo que OOMKilled devolve false. No browser, estes casos parecem idênticos. Em docker inspect, ficam separados por um único campo.

Defina o limite do heap do Node abaixo do limite do contentor. Se o limite do heap for o mais elevado dos dois, o V8 continua a alocar memória depois do ponto em que o kernel intervém. Assim, o garbage collector nunca atinge o seu próprio limite e ocorre sempre a falha mais grave, sem logs para consultar.

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    environment:
      - NODE_OPTIONS=--max-old-space-size=<MiB, below the container limit>
    deploy:
      resources:
        limits:
          memory: <your container limit>

Escolha ambos os valores com base nos recursos efetivamente disponíveis na VPS e reserve memória para a base de dados, o proxy e o sistema operativo. docker stats --no-stream apresenta a utilização atual junto ao limite em vigor, para que possa confirmar que o limite definido é o limite aplicado pelo Docker. Como são aplicados os limites de memória do Compose explica qual chave prevalece quando existem várias configurações.

Os dados das execuções acumulam-se por baixo do sistema

Uma única execução contém a saída de todos os nós enquanto decorre, e o n8n armazena esses dados. Daqui resultam duas consequências. O pico de memória de uma execução é determinado pelo maior lote de dados que circula pelo workflow. Por isso, um workflow que processa dez mil linhas de uma vez é um programa diferente do mesmo workflow a processar duzentas de cada vez. Além disso, a cópia armazenada continua a crescer até ser eliminada.

A limpeza resolve o segundo problema. Em agosto de 2026, as predefinições são a limpeza ativada, EXECUTIONS_DATA_MAX_AGE em 336 horas (14 dias) e EXECUTIONS_DATA_PRUNE_MAX_COUNT em 10000. Estes valores são elevados para um VPS pequeno com SQLite, onde um único ficheiro contém tudo e o mesmo processo que disponibiliza o editor tem de o ler e escrever.

environment:
  - EXECUTIONS_DATA_PRUNE=true
  - EXECUTIONS_DATA_MAX_AGE=72
  - EXECUTIONS_DATA_PRUNE_MAX_COUNT=1000
  - EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
  - EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=false

EXECUTIONS_DATA_SAVE_ON_SUCCESS=none é a definição agressiva. Mantém as execuções falhadas para depuração e elimina as concluídas com sucesso. Tome esta decisão de forma consciente, porque um workflow que produza uma saída incorreta sem gerar um erro não deixará nada para inspecionar. A limpeza também marca primeiro as linhas como eliminadas e remove-as numa passagem posterior. Além disso, o SQLite reutiliza as páginas libertadas em vez de as devolver ao sistema, pelo que o ficheiro no disco não diminui imediatamente depois de alterar a definição.

Para reduzir o pico em vez do total armazenado, mova menos dados por execução. Divida os trabalhos grandes em sub-workflows que devolvam resultados pequenos ao workflow principal, use o nó Loop Over Items para processar lotes e mantenha datasets completos fora do nó Code.

Ficheiros binários não devem passar pela memória

N8N_DEFAULT_BINARY_DATA_MODE assume default por predefinição. Esta configuração mantém os dados binários na memória da execução em curso. Cada ficheiro transferido por um nó e cada cópia entregue ao nó seguinte permanecem na memória até à execução terminar. Um único workflow que transfira alguns anexos grandes pode fazer o processo ultrapassar um limite que as operações normais com JSON nunca atingem. Por isso, a falha ocorre num workflow específico e não após um determinado período.

environment:
  - N8N_DEFAULT_BINARY_DATA_MODE=filesystem

Com filesystem, os dados binários são gravados em N8N_BINARY_DATA_STORAGE_PATH. Por predefinição, este caminho fica dentro da pasta do utilizador do n8n e, portanto, no mesmo volume que o restante conteúdo. Confirme se o volume tem espaço disponível antes de ativar esta opção. N8N_PAYLOAD_SIZE_MAX define o tamanho máximo do payload recebido por webhook, em MiB (mebibytes), e assume 16 por predefinição. Aumentar este valor permite receber pedidos maiores, mas implica aceitar o custo adicional na memória.

Tudo o que partilha o servidor concorre pela mesma RAM. Se os processos OOM kill começaram depois de adicionar um contentor de base de dados, executar a base de dados no Docker ou no host é a escolha que está agora a fazer.

Política de reinício e recuperação após um reboot

Um contentor sem uma política de reinício permanece parado depois de terminar e também depois de o host reiniciar. restart: unless-stopped volta a iniciá-lo nos dois casos, mas respeita um contentor que tenha sido parado manualmente. restart: always também reinicia um contentor parado deliberadamente quando o Docker iniciar novamente.

O n8n disponibiliza um endpoint de saúde, identificado por N8N_ENDPOINT_HEALTH, que usa healthz por predefinição. Consulte-o primeiro a partir do host para confirmar que o caminho está correto na sua instância.

curl -fsS http://127.0.0.1:5678/healthz
docker exec n8n which wget curl
sudo systemctl is-enabled docker

Um healthcheck, por si só, não reinicia nada. O Compose marca o contentor como não saudável e não faz mais nada. Por isso, o healthcheck precisa de uma política de reinício ou de um monitor externo ao lado dele para produzir algum efeito. Escrever um healthcheck que realmente atua e fazer a stack iniciar novamente depois de um reboot abrangem as duas partes.

O workflow que nunca é executado embora o n8n esteja operacional

Este workflow não apresenta nenhum banner nem reinicia. O contentor está em execução, o editor funciona e a execução esperada não aparece na lista de execuções. Quatro causas explicam a maioria destes casos.

  • O workflow não está ativo. Um Schedule Trigger só é executado no percurso de produção. Testá-lo no canvas não agenda nada.
  • O fuso horário não é o seu. GENERIC_TIMEZONE usa America/New_York por predefinição. Por isso, um agendamento definido para 09:00 é executado às 09:00 nesse fuso até definir GENERIC_TIMEZONE e TZ com o seu fuso horário.
  • O período de indisponibilidade não é compensado depois. Os triggers são registados quando o n8n arranca. Por isso, um agendamento que venceu enquanto o contentor reiniciava não é executado com atraso. A próxima execução ocorre no próximo horário previsto depois do arranque.
  • O workflow foi desativado automaticamente. N8N_WORKFLOW_AUTODEACTIVATION_ENABLED está desativado por predefinição. Quando está ativo, um workflow que continua a falhar é retirado de publicação. Depois disso, parece exatamente um workflow que nunca foi ativado.

Abra a lista de execuções e filtre pelo workflow. Uma entrada com falha indica um problema no workflow. Se a falha foi um erro 429 contra outro serviço alojado no mesmo servidor, o limite pertence a esse serviço, não ao n8n. O guia passo a passo sobre erros 429 no SearXNG mostra como distinguir o próprio limitador de taxa dos motores que estão a bloquear o IP do seu servidor. A ausência total de entradas indica um problema no trigger. É nesses quatro pontos que deve procurar.

O que alterar primeiro

  1. Leia STATUS, RestartCount e OOMKilled no seu próprio contentor antes de editar qualquer ficheiro.
  2. Se o contentor nunca parou, corrija os cabeçalhos de atualização do proxy e o tempo limite de inatividade.
  3. Se OOMKilled for verdadeiro, defina deliberadamente um limite para o contentor, coloque o limite máximo de memória do Node abaixo desse valor e altere os dados binários para filesystem.
  4. Se nada foi acionado, confirme se o workflow está ativo e se o fuso horário da instância é o seu.

A maior parte disto é configuração que se define uma vez e depois não precisa de manutenção, sobre uma instalação funcional. Se ainda estiver a montar essa instalação, o guia do n8n no Docker com HTTPS é a base a que estas definições pertencem.

FAQ

Por que o editor do n8n mostra um aviso de ligação perdida quando o contentor está em execução?

O editor mantém um WebSocket aberto para transmitir o progresso da execução. Se o reverse proxy não encaminhar os cabeçalhos Connection: Upgrade e Upgrade: websocket, ou não usar HTTP/1.1 no upstream, a atualização nunca é concluída e o navegador tenta ligar-se novamente indefinidamente, enquanto o n8n continua saudável. No nginx, precisa de proxy_http_version 1.1 e das duas linhas proxy_set_header, além de um proxy_read_timeout superior aos 60 segundos predefinidos, para que um separador inativo não seja desligado. Verifique a configuração em execução com sudo nginx -T, e não com o ficheiro que editou.

Como distingo uma eliminação por falta de memória de uma falha normal?

Execute docker inspect n8n | grep -iE 'OOMKilled|ExitCode|RestartCount' e leia a flag OOMKilled. True significa que o kernel eliminou o processo por ultrapassar um limite de memória. Não haverá informação útil no log do contentor, porque o processo não teve oportunidade de escrever. False, juntamente com um erro de heap e um stack trace no fim de docker logs, significa que o Node.js atingiu o seu próprio limite de heap V8 e terminou por iniciativa própria. Defina NODE_OPTIONS=--max-old-space-size abaixo do limite do contentor para obter a segunda falha, que é a que deixa evidências.

A limpeza dos dados de execução liberta espaço em disco imediatamente?

Não. EXECUTIONS_DATA_PRUNE marca as execuções antigas para eliminação e uma passagem posterior remove-as, de acordo com o agendamento definido por EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL. Com SQLite, o ficheiro também reutiliza as páginas libertadas em vez de as devolver ao sistema de ficheiros. Por isso, o tamanho em disco mantém-se estável durante algum tempo depois de as linhas serem removidas. Defina EXECUTIONS_DATA_MAX_AGE e EXECUTIONS_DATA_PRUNE_MAX_COUNT com valores adequados ao seu servidor. Volte a verificar no dia seguinte, e não imediatamente.

Por que motivo o meu workflow agendado não foi executado enquanto o n8n estava a reiniciar?

O n8n regista os triggers quando o processo arranca. Não repõe os agendamentos cujo prazo ocorreu enquanto estava parado. Por isso, um ciclo de reinícios produz silêncio em vez de várias execuções de recuperação. A execução seguinte ocorre no próximo horário devido depois do arranque. Se precisar de execuções que não possam ser perdidas, inicie o workflow a partir de um sistema externo que invoque um webhook. Assim, a lógica de novas tentativas fica fora do n8n.

Um healthcheck reinicia o n8n quando este deixa de responder?

Não, por si só. Um healthcheck do Compose apenas marca o contentor como saudável ou não saudável. O reinício é responsabilidade da política de reinício. Por isso, restart: unless-stopped repõe o contentor depois de este terminar e também o repõe depois de um reboot do host, desde que o serviço Docker esteja ativado. Confirme isso com sudo systemctl is-enabled docker. Para agir especificamente quando o contentor fica não saudável, precisa de um watcher externo ao Docker que leia o estado e reinicie o serviço.