Nginx Proxy Manager com Docker na VPS

O Nginx Proxy Manager (NPM) é um painel web para gerenciar proxy reverso, certificados SSL Let's Encrypt e redirects na VPS, sem precisar editar arquivos de configuração do Nginx. É ideal para hospedar múltiplos apps (n8n, Chatwoot, WordPress, etc.) em subdomínios diferentes com HTTPS automático.

Por que usar Nginx Proxy Manager?

Sem NPM, você edita manualmente o nginx.conf para cada app, executa o Certbot para cada domínio e gerencia renovações. Com NPM, tudo é feito pela interface web em minutos:

bash
# Comparativo de fluxo:

# Sem NPM (manual):
#   1. Editar /etc/nginx/sites-available/app.conf
#   2. docker compose run certbot certonly -d app.dominio.com
#   3. Adicionar ssl_certificate ao nginx.conf
#   4. nginx -s reload
#   (repetir para cada app)

# Com NPM (interface web):
#   1. Acessar o painel em :81
#   2. Add Proxy Host → preencher domínio + porta do app
#   3. Ativar "SSL" → Let's Encrypt → salvar
#   (certificado gerado automaticamente)

Instalar o Nginx Proxy Manager

Crie o diretório /opt/npm e o docker-compose.yml com a configuração mínima:

bash
mkdir -p /opt/npm
cat > /opt/npm/docker-compose.yml << 'EOF'
services:
  npm:
    image: jc21/nginx-proxy-manager:latest
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "81:81"   # Painel de administração
    volumes:
      - npm_data:/data
      - npm_letsencrypt:/etc/letsencrypt

volumes:
  npm_data:
  npm_letsencrypt:
EOF

cd /opt/npm
docker compose up -d

# Acessar o painel: http://IP_DA_VPS:81
# Login padrão: admin@example.com / changeme

Adicionar um Proxy Host (subdomínio + SSL)

Com o NPM instalado, configure um proxy host para qualquer app rodando na VPS:

bash
# No painel NPM (http://IP_DA_VPS:81):
# Hosts → Proxy Hosts → Add Proxy Host

# Aba Details:
#   Domain Names: app.seudominio.com.br
#   Scheme: http
#   Forward Hostname/IP: 172.17.0.1  (IP do Docker host)
#   Forward Port: PORTA_DO_APP (ex: 5678 para n8n, 3000 para Chatwoot)
#   Websockets Support: ON (para n8n, Chatwoot, etc.)
#   Block Common Exploits: ON

# Aba SSL:
#   SSL Certificate: Request a new SSL Certificate
#   Force SSL: ON
#   HTTP/2 Support: ON
#   E-mail: seu@email.com
#   → Save

Conectar apps Docker na rede do NPM

Para usar o nome do serviço como hostname (mais seguro que expor portas no host), conecte os apps à mesma rede externa do NPM:

yaml
# Criar rede compartilhada (uma vez só)
docker network create npm_proxy

# No docker-compose.yml de cada app, adicionar:
networks:
  default:
    external: true
    name: npm_proxy

# No docker-compose.yml do NPM:
services:
  npm:
    networks:
      - npm_proxy

networks:
  npm_proxy:
    external: true

# Agora no Proxy Host:
#   Forward Hostname/IP: nome_do_servico
#   Forward Port: porta_interna (sem expor no host)

Proteger o painel do NPM com acesso restrito

O painel na porta 81 não deve ficar exposto. Bloqueie no firewall e acesse via SSH tunnel:

bash
# Bloquear porta 81 externamente (manter apenas 80 e 443 abertas)
ufw deny 81
ufw allow 80
ufw allow 443

# Acessar o painel via SSH tunnel (no seu computador local)
ssh -L 8181:localhost:81 root@IP_DA_VPS

# Abrir no browser local: http://localhost:8181

Não quer configurar manualmente?

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

Perguntas frequentes

NPM: interface web, configuração simples, ideal para equipes sem experiência em proxy reverso ou menos de 10 apps. Traefik: configuração via labels Docker (sem interface), auto-discovery de containers, melhor para infraestrutura grande e equipes de DevOps. Para uso pessoal ou pequenos projetos: NPM. Para cluster Kubernetes ou dezenas de microserviços: Traefik.

Coolify tem o próprio proxy Traefik/Caddy integrado, não faz sentido combinar. Portainer é apenas uma interface para gerenciar containers Docker, sem proxy, combinar com NPM é perfeitamente válido e muito comum.

Sim. Em cada Proxy Host, aba Access Lists, você cria uma lista com usuário/senha. O Nginx exige autenticação antes de passar a requisição para o app. Útil para proteger painéis internos como Grafana, phpMyAdmin, etc.

Os volumes npm_data e npm_letsencrypt contêm tudo. Faça backup com: docker run --rm -v npm_npm_data:/data -v $(pwd):/out alpine tar czf /out/npm-data.tar.gz /data. Mantenha backups regulares, perder o volume npm_letsencrypt não é problema grave (o Certbot regenera os certificados), mas npm_data tem as configurações dos hosts.

Sim, mas requer o desafio DNS-01 em vez do HTTP-01. Você precisa configurar as credenciais da API do seu provedor DNS (Cloudflare, Route53, etc.) no NPM para que ele crie os registros TXT de validação automaticamente. Veja a documentação do NPM para a lista de provedores DNS suportados.