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.

cerca de 60 minjunho/2026 · Ubuntu 24.04 LTS

Antes de começar

VPS mínima
2 vCPU · 4 GB RAM · 40 GB SSD (Runstack Pro recomendado)
Sistema
Ubuntu 24.04 LTS
Também
  • 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. 1

    Atualizar o sistema e instalar dependências

    Instale Docker, Nginx e utilitários necessários.

    bash
    apt 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. 2

    Criar a estrutura de diretórios

    Centralize todos os arquivos da stack em /opt/stack.

    bash
    mkdir -p /opt/stack
    cd /opt/stack
  3. 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)"
  4. 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_AQUI
  5. 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: bridge
  6. 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;
  7. 7

    Subir a stack

    Inicie todos os serviços e verifique que estão saudáveis.

    bash
    cd /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=30
  8. 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 -t
  9. 9

    Obter certificados SSL e configurar firewall

    Emita certificados para ambos os subdomínios e configure o UFW.

    bash
    certbot --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. 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"

Não quer configurar manualmente?

Implante o n8n + Evolution API em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Se der problema

O usuário `evolution` deve ter permissão para criar schemas. Verifique se ele é o OWNER do banco evolution_db.

bash
# Conectar ao postgres e verificar:
docker compose exec postgres psql -U postgres -c "\du"
docker compose exec postgres psql -U postgres -c "\l"

O banco `n8n` precisa existir. Verifique se o init-db.sql foi executado na criação do volume do PostgreSQL.

bash
docker compose logs postgres | grep "init-db"
docker compose exec postgres psql -U postgres -c "\l"

O WEBHOOK_URL do n8n deve ser a URL pública HTTPS. Verifique a variável N8N_HOST no .env e se o Nginx está funcionando para o subdomínio do n8n.

A senha do Redis no CACHE_REDIS_URI da Evolution deve corresponder ao `--requirepass` configurado no container Redis. Verifique as variáveis no .env.

bash
docker compose logs redis --tail=20
docker compose logs evolution-api --tail=20

A stack completa consome 2-3 GB de RAM em idle. Em VPS com menos de 4 GB, considere upgrade para o Runstack Pro. Verifique o uso com `docker stats`.

bash
docker stats --no-stream

Perguntas frequentes

Sim, mas o Chatwoot requer pelo menos 2 GB adicionais de RAM (Sidekiq + Rails + PostgreSQL). Adicione o Chatwoot ao docker-compose.yml usando o mesmo PostgreSQL e Redis, com um banco dedicado criado no init-db.sql. Recomendamos VPS com 6-8 GB para essa combinação.

Como ambos estão na mesma rede Docker (stack-net), o n8n pode acessar a Evolution API internamente via `http://evolution-api:8080`. No n8n, use o nó HTTP Request com essa URL interna e o header `apikey`.

Faça dump do PostgreSQL: `docker compose exec postgres pg_dumpall -U postgres > backup.sql`. Faça backup dos volumes: n8n_data (credenciais e workflows) e evolution_instances (sessões WhatsApp conectadas). Automatize com cron.

Sim. Configure um webhook global ou por instância na Evolution API apontando para `https://n8n.seudominio.com.br/webhook/evolution` (ou o caminho do seu trigger no n8n). O n8n processa os eventos e executa os workflows.

Para alto volume, considere mover o PostgreSQL para um servidor dedicado (Runstack Pro com PostgreSQL nativo), usar Redis gerenciado e rodar n8n em modo queue com workers separados. A estrutura do docker-compose.yml deste guia é o ponto de partida para essa evolução.