Stack n8n + Evolution API + PostgreSQL em uma VPS
Este guia monta a stack completa de automação de WhatsApp mais usada no Brasil: n8n para orquestração de workflows, Evolution API para conexão com WhatsApp, PostgreSQL compartilhado e Redis — tudo em um único docker-compose.yml com Nginx roteando os subdomínios. Reserva 60 minutos e uma VPS com pelo menos 4 GB de RAM.
Pré-requisitos
- VPS mínima: 2 vCPU · 4 GB RAM · 40 GB SSD (Runstack Pro recomendado)
- Sistema: Ubuntu 24.04 LTS
- Docker e Docker Compose instalados (veja /tutorial/como-instalar-docker)
- Dois subdomínios DNS apontados para o IP da VPS (ex.: n8n.seudominio.com.br e evo.seudominio.com.br)
- Portas 80 e 443 abertas no firewall
- Nginx instalado
Instalação passo a passo
- 1
Atualizar o sistema e instalar dependências
Instale Docker, Nginx e utilitários necessários.
bashapt update && apt upgrade -y apt install -y curl wget nginx certbot python3-certbot-nginx # Instalar Docker curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh docker --version && docker compose version - 2
Criar a estrutura de diretórios
Centralize todos os arquivos da stack em /opt/stack.
bashmkdir -p /opt/stack cd /opt/stack - 3
Gerar todos os segredos da stack
Gere senhas e chaves únicas para cada serviço antes de criar os arquivos de configuração.
bash# Senha compartilhada do PostgreSQL echo "POSTGRES_PASSWORD: $(openssl rand -hex 24)" # Senha do Redis echo "REDIS_PASSWORD: $(openssl rand -hex 16)" # Chave de encriptação do n8n echo "N8N_ENCRYPTION_KEY: $(openssl rand -hex 24)" # API key da Evolution API echo "EVOLUTION_API_KEY: $(openssl rand -hex 24)"DicaGuarde todos esses valores — eles serão usados no .env a seguir. - 4
Criar o arquivo .env
Configure todas as variáveis da stack em um único .env compartilhado.
.env# /opt/stack/.env # ── PostgreSQL ────────────────────────────────────────────── POSTGRES_PASSWORD=SUA_SENHA_POSTGRES_AQUI # ── Redis ──────────────────────────────────────────────────── REDIS_PASSWORD=SUA_SENHA_REDIS_AQUI # ── n8n ───────────────────────────────────────────────────── N8N_HOST=n8n.seudominio.com.br N8N_ENCRYPTION_KEY=SUA_CHAVE_N8N_AQUI GENERIC_TIMEZONE=America/Sao_Paulo # ── Evolution API ──────────────────────────────────────────── EVOLUTION_SERVER_URL=https://evo.seudominio.com.br EVOLUTION_API_KEY=SUA_API_KEY_EVOLUTION_AQUIAtençãoSubstitua TODOS os valores de placeholder pelos segredos gerados no passo anterior. Nunca use valores de exemplo em produção. - 5
Criar o docker-compose.yml da stack completa
Este arquivo unifica PostgreSQL (com bancos separados para cada serviço), Redis, n8n e Evolution API em uma única rede Docker.
docker-compose.yml# /opt/stack/docker-compose.yml services: # ── Banco de dados compartilhado ───────────────────────────── postgres: image: postgres:16-alpine restart: always environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 10 networks: - stack-net # ── Redis compartilhado ────────────────────────────────────── redis: image: redis:alpine restart: always command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes volumes: - redis_data:/data networks: - stack-net # ── n8n ────────────────────────────────────────────────────── n8n: image: docker.n8n.io/n8nio/n8n:latest restart: always ports: - "127.0.0.1:5678:5678" environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=n8n - DB_POSTGRESDB_USER=n8n - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD} - N8N_HOST=${N8N_HOST} - N8N_PORT=5678 - N8N_PROTOCOL=https - WEBHOOK_URL=https://${N8N_HOST}/ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} - GENERIC_TIMEZONE=${GENERIC_TIMEZONE} - TZ=${GENERIC_TIMEZONE} volumes: - n8n_data:/home/node/.n8n depends_on: postgres: condition: service_healthy networks: - stack-net # ── Evolution API ───────────────────────────────────────────── evolution-api: image: evoapicloud/evolution-api:latest restart: always ports: - "127.0.0.1:8080:8080" environment: - SERVER_URL=${EVOLUTION_SERVER_URL} - SERVER_PORT=8080 - DATABASE_PROVIDER=postgresql - DATABASE_CONNECTION_URI=postgresql://evolution:${POSTGRES_PASSWORD}@postgres:5432/evolution_db?schema=evolution_api - CACHE_REDIS_ENABLED=true - CACHE_REDIS_URI=redis://:default@redis:6379/6 - AUTHENTICATION_API_KEY=${EVOLUTION_API_KEY} - LANGUAGE=pt-BR volumes: - evolution_instances:/evolution/instances depends_on: postgres: condition: service_healthy networks: - stack-net volumes: postgres_data: redis_data: n8n_data: evolution_instances: networks: stack-net: driver: bridgeDicaO PostgreSQL compartilhado usa um script de inicialização (init-db.sql) para criar os bancos separados do n8n e da Evolution API. Esse script é criado no próximo passo. - 6
Criar o script de inicialização do banco
O PostgreSQL executa este script na primeira inicialização para criar os bancos e usuários de cada serviço.
init-db.sql# /opt/stack/init-db.sql -- Criar usuário e banco para o n8n CREATE USER n8n WITH PASSWORD 'SUA_SENHA_POSTGRES_AQUI'; CREATE DATABASE n8n OWNER n8n; -- Criar usuário e banco para a Evolution API CREATE USER evolution WITH PASSWORD 'SUA_SENHA_POSTGRES_AQUI'; CREATE DATABASE evolution_db OWNER evolution;DicaNa Evolution API, o schema `evolution_api` é criado automaticamente pelo Prisma na primeira inicialização — não é necessário criá-lo manualmente.AtençãoSubstitua SUA_SENHA_POSTGRES_AQUI pelo mesmo valor de POSTGRES_PASSWORD do .env. Este arquivo é executado apenas na criação inicial do volume — alterar o arquivo depois não tem efeito sem recriar o volume. - 7
Subir a stack
Inicie todos os serviços e verifique que estão saudáveis.
bashcd /opt/stack docker compose up -d # Acompanhar a inicialização docker compose ps # Verificar logs individualmente se necessário docker compose logs postgres --tail=30 docker compose logs n8n --tail=30 docker compose logs evolution-api --tail=30DicaA Evolution API pode levar 60-90 segundos para inicializar na primeira vez enquanto o Prisma aplica o schema no banco. - 8
Configurar Nginx para os dois serviços
Crie virtual hosts separados para o n8n e para a Evolution API.
bash# Virtual host n8n cat > /etc/nginx/sites-available/n8n << 'NGINXEOF' server { listen 80; server_name n8n.seudominio.com.br; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name n8n.seudominio.com.br; ssl_certificate /etc/letsencrypt/live/n8n.seudominio.com.br/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/n8n.seudominio.com.br/privkey.pem; location / { proxy_pass http://127.0.0.1:5678; 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_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_buffering off; proxy_read_timeout 3600s; } } NGINXEOF # Virtual host Evolution API cat > /etc/nginx/sites-available/evolution-api << 'NGINXEOF' server { listen 80; server_name evo.seudominio.com.br; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name evo.seudominio.com.br; ssl_certificate /etc/letsencrypt/live/evo.seudominio.com.br/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/evo.seudominio.com.br/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; 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_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } } NGINXEOF ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/n8n ln -s /etc/nginx/sites-available/evolution-api /etc/nginx/sites-enabled/evolution-api nginx -tAtençãoSubstitua n8n.seudominio.com.br e evo.seudominio.com.br pelos seus subdomínios reais. - 9
Obter certificados SSL e configurar firewall
Emita certificados para ambos os subdomínios e configure o UFW.
bashcertbot --nginx \ -d n8n.seudominio.com.br \ -d evo.seudominio.com.br \ --non-interactive \ --agree-tos \ --email seu@email.com systemctl reload nginx # Configurar firewall ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp ufw --force enable ufw status verbose - 10
Verificar a stack completa
Confirme que todos os serviços estão acessíveis.
bash# Status de todos os containers docker compose -f /opt/stack/docker-compose.yml ps # Testar n8n curl -I https://n8n.seudominio.com.br # Testar Evolution API curl -s https://evo.seudominio.com.br/ | head -c 100 # Listar instâncias da Evolution API curl -s https://evo.seudominio.com.br/instance/fetchInstances \ -H "apikey: SUA_API_KEY_EVOLUTION_AQUI"DicaAcesse https://n8n.seudominio.com.br para criar a conta de owner do n8n. Para integrar a Evolution API com o n8n, use o nó HTTP Request apontando para https://evo.seudominio.com.br com o header apikey.
$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o n8n + Evolution API em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.
Troubleshooting
Perguntas frequentes
[VERIFICAR antes de publicar]
- 1. Confirme que o formato da DATABASE_CONNECTION_URI da Evolution API (`?schema=evolution_api`) ainda é necessário na versão atual.
- 2. Verifique se o CACHE_REDIS_URI aceita senha via formato `redis://:senha@host:porta/db` na versão atual da Evolution API.
- 3. Teste a criação dos bancos via init-db.sql — confirme que a senha do usuário `evolution` e `n8n` usa o mesmo POSTGRES_PASSWORD do container postgres.