Como instalar o n8n em uma VPS com Docker e HTTPS

Atualizado em 21/09/2026 25 min Intermediário

O n8n é uma ferramenta de automação que conecta serviços entre si — recebe um webhook, consulta uma API, grava no banco, dispara um e-mail. Rodar na sua própria VPS tira o limite de execuções da versão em nuvem e mantém credenciais e dados dentro da sua infraestrutura.

Este guia sobe o n8n em produção: com PostgreSQL em vez do banco SQLite padrão, atrás de um proxy reverso que emite e renova o certificado HTTPS sozinho, e com os dados em volumes que sobrevivem a atualizações.

Antes de começar

  • Uma VPS com Ubuntu 22.04 ou 24.04 e acesso root.
  • Um domínio ou subdomínio apontado para o IP da VPS (por exemplo n8n.seudominio.com.br).
  • 2 GB de RAM atendem para uso pessoal e fluxos leves. A partir de dezenas de execuções simultâneas ou fluxos que processam arquivos, vá de 4 GB.

Aponte o domínio para a VPS

Antes de qualquer comando, crie um registro A no DNS do seu domínio apontando para o IP da VPS. Sem isso o certificado HTTPS não é emitido, porque a autoridade certificadora precisa alcançar o servidor pelo nome.

Se você usa Cloudflare, deixe a nuvem cinza (DNS only) durante a instalação. Com o proxy laranja ligado, o desafio do certificado não chega até a VPS.

confira a propagação
dig +short n8n.seudominio.com.br

O comando precisa responder com o IP da sua VPS. Se não responder, espere a propagação antes de seguir — pode levar alguns minutos.

Atualize o sistema e feche o firewall

Comece pelo básico: sistema atualizado e apenas as portas necessárias abertas. O n8n vai ficar atrás do proxy, então só 22 (SSH), 80 e 443 precisam responder.

terminal
apt update && apt upgrade -y

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
ufw status

Confirme que a regra do OpenSSH está na lista antes de habilitar o firewall. Ligar o ufw sem ela derruba a sua própria conexão.

Instale o Docker

O script oficial instala o Docker Engine e o plugin Compose nas versões atuais, direto do repositório da Docker.

terminal
curl -fsSL https://get.docker.com | sh

docker --version
docker compose version

Os dois comandos de versão precisam responder. Se o docker compose não for encontrado, você está numa instalação antiga com o comando separado docker-compose — desinstale e refaça pelo script acima.

Crie a estrutura e o arquivo de ambiente

Separe configuração de dados. As senhas ficam em .env, fora do docker-compose.yml, o que facilita versionar o segundo sem vazar o primeiro.

terminal
mkdir -p /opt/n8n && cd /opt/n8n

# gera senhas fortes e grava o arquivo de ambiente
cat > .env <<EOF
DOMINIO=n8n.seudominio.com.br
[email protected]

POSTGRES_USER=n8n
POSTGRES_PASSWORD=$(openssl rand -hex 24)
POSTGRES_DB=n8n

N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
FUSO=America/Sao_Paulo
EOF

chmod 600 .env
cat .env

Guarde a N8N_ENCRYPTION_KEY em lugar seguro. É com ela que o n8n cifra as credenciais dos seus fluxos: perdida a chave, todas as credenciais salvas param de funcionar e precisam ser recadastradas.

Escreva o docker-compose.yml

São três serviços: o banco PostgreSQL, o n8n e o Caddy, que faz o proxy reverso e cuida do certificado HTTPS sozinho — sem certbot, sem cron de renovação.

terminal
cat > /opt/n8n/docker-compose.yml <<'EOF'
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${DOMINIO}
      N8N_PORT: 5678
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://${DOMINIO}/
      GENERIC_TIMEZONE: ${FUSO}
      TZ: ${FUSO}
      N8N_RUNNERS_ENABLED: "true"
    volumes:
      - n8n_data:/home/node/.n8n

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      DOMINIO: ${DOMINIO}
      EMAIL: ${EMAIL}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

volumes:
  postgres_data:
  n8n_data:
  caddy_data:
  caddy_config:
EOF

O WEBHOOK_URL é o detalhe que mais gera dor de cabeça: sem ele, os webhooks que o n8n gera apontam para localhost e nenhum serviço externo consegue chamar seus fluxos.

Configure o proxy com HTTPS automático

O Caddyfile tem três linhas. Ele emite o certificado no primeiro acesso, renova sozinho e redireciona HTTP para HTTPS sem você configurar nada.

terminal
cat > /opt/n8n/Caddyfile <<'EOF'
{$DOMINIO} {
	tls {$EMAIL}
	reverse_proxy n8n:5678
}
EOF

Suba tudo e crie a conta de administrador

Com os três arquivos no lugar, é um comando. A primeira subida baixa as imagens e pode levar alguns minutos.

terminal
cd /opt/n8n
docker compose up -d

# acompanhe até ver "Editor is now accessible"
docker compose logs -f n8n

Abra https://n8n.seudominio.com.br no navegador. Na primeira visita o n8n pede para criar a conta de dono — faça isso imediatamente: enquanto ninguém criar, qualquer pessoa que acessar o endereço pode se tornar o administrador.

Se o navegador reclamar do certificado, espere um minuto e recarregue. O Caddy emite na primeira requisição e leva alguns segundos.

Deixe o backup pronto

O que precisa ser salvo são dois volumes: o banco (fluxos, execuções, usuários) e a pasta do n8n (credenciais cifradas). Este script gera um dump diário e mantém os últimos sete dias.

terminal
cat > /opt/n8n/backup.sh <<'EOF'
#!/bin/bash
set -e
cd /opt/n8n
source .env
DESTINO=/opt/n8n/backups
mkdir -p $DESTINO
DATA=$(date +%Y%m%d-%H%M)

docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" | gzip > "$DESTINO/n8n-$DATA.sql.gz"
docker run --rm -v n8n_n8n_data:/dados -v "$DESTINO":/backup alpine tar czf "/backup/n8n-arquivos-$DATA.tar.gz" -C /dados .

find "$DESTINO" -name '*.gz' -mtime +7 -delete
EOF

chmod +x /opt/n8n/backup.sh
/opt/n8n/backup.sh && ls -lh /opt/n8n/backups

# roda todo dia às 3h
(crontab -l 2>/dev/null; echo '0 3 * * * /opt/n8n/backup.sh') | crontab -

Backup que mora no mesmo disco não é backup. Copie a pasta /opt/n8n/backups para fora da VPS — outro servidor, um bucket, sua máquina.

Se algo não funcionar

O navegador não abre o endereço ou mostra erro de certificado

Quase sempre é DNS. Confirme que o domínio responde com o IP da VPS e que, no Cloudflare, o registro está em DNS only durante a emissão. Depois veja o log do Caddy:

terminal
docker compose logs caddy | tail -30

Os webhooks não são chamados pelos serviços externos

Verifique se o WEBHOOK_URL está com o domínio real e com a barra no final. Depois de corrigir o .env, recrie o contêiner com docker compose up -d --force-recreate n8n.

O n8n reinicia sozinho ou fica lento com muitos fluxos

Olhe a memória. Se a VPS estiver constantemente perto do limite, é hora de subir de plano — o n8n carrega cada execução em memória.

terminal
free -h
docker stats --no-stream
VPS com acesso root, NVMe e rota nacional

A partir de 2 GB de RAM para fluxos pessoais; 4 GB quando o volume aperta. Ativação automática depois da confirmação do pagamento.

Ver planos de VPS

Perguntas frequentes

Quanta memória o n8n consome de verdade?

Parado com poucos fluxos, algo em torno de 300 a 500 MB somando n8n e PostgreSQL. O consumo sobe conforme o número de execuções simultâneas e o tamanho dos dados que cada fluxo carrega. Em 2 GB você roda uso pessoal e automações de rotina com folga; fluxos que manipulam arquivos ou rodam em paralelo pedem 4 GB.

Preciso mesmo do PostgreSQL? O n8n não funciona sem ele?

Funciona — o padrão é SQLite. Mas o arquivo SQLite cresce com o histórico de execuções e fica lento, e a migração depois dá mais trabalho do que já começar no PostgreSQL. Para qualquer uso que não seja teste, comece com banco.

Como atualizo o n8n depois?

Rode o backup, puxe a imagem nova e recrie: cd /opt/n8n && ./backup.sh && docker compose pull && docker compose up -d. Os dados ficam nos volumes, então a atualização não perde nada. Leia as notas da versão antes de atualizações de versão maior.

Posso rodar o n8n junto com outros serviços na mesma VPS?

Pode, e é comum. O Caddy já está de pé nas portas 80 e 443 — basta acrescentar outro bloco no Caddyfile apontando para o novo contêiner. O que limita é memória, não o proxy.

Continue por aqui