Como instalar o n8n em uma VPS com Docker e HTTPS
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
free -h
docker stats --no-stream
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.
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
Como instalar o Docker em uma VPS Ubuntu
Base para qualquer serviço auto-hospedado: Docker, Compose, usuário sem root e limpeza automática de imagens.
Como instalar o Typebot em uma VPS
Construtor de conversas auto-hospedado, com builder e viewer em subdomínios separados e armazenamento de arquivos.
Como instalar a Evolution API em uma VPS
API não oficial de WhatsApp com PostgreSQL e Redis, pronta para integrar com n8n, Typebot ou seu próprio sistema.