TL;DR — Resumo Rápido
Configure o Nginx como proxy reverso e balanceador de carga com SSL. Cobre proxy_pass, Let's Encrypt, algoritmos de balanceamento, WebSocket e rate limiting.
O Nginx alimenta mais de 34% dos sites mais visitados do mundo — e grande parte desse tráfego flui por ele não como servidor web, mas como proxy reverso e balanceador de carga. Configurar o Nginx como proxy reverso com terminação SSL fornece um único ponto de entrada endurecido que distribui a carga entre servidores backend, descarrega o TLS da sua aplicação e adiciona cache, rate limiting e cabeçalhos de segurança em um só lugar. Este guia cobre cada camada dessa pilha: fundamentos do proxy reverso, terminação SSL com Let’s Encrypt, os quatro algoritmos de balanceamento, proxying de WebSocket, cache de respostas, rate limiting, cabeçalhos de segurança, HTTP/2 e HTTP/3, monitoramento e um cenário real com cluster Node.js.
Pré-requisitos
Antes de começar, certifique-se de ter:
- Ubuntu 22.04 ou 24.04 (os comandos se aplicam a qualquer distro baseada em Debian)
- Nginx 1.18 ou superior (
sudo apt install nginx) - Um domínio registrado apontando para o IP público do seu servidor
- Acesso ao terminal com privilégios sudo
- Pelo menos dois servidores ou processos de aplicação backend (para balanceamento de carga)
Fundamentos do Proxy Reverso
Um proxy reverso fica entre a internet e um ou mais servidores backend. Os clientes se conectam ao Nginx; o Nginx encaminha a requisição para o backend apropriado e retorna a resposta. O backend nunca precisa de um IP público.
A diretiva central é proxy_pass:
server {
listen 80;
server_name app.exemplo.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
As quatro diretivas proxy_set_header são indispensáveis em qualquer configuração de produção. Sem X-Forwarded-For, os logs da sua aplicação mostram apenas o IP do servidor Nginx. Sem X-Forwarded-Proto, seu app não consegue distinguir HTTP de HTTPS e pode gerar loops de redirecionamento incorretos.
Defina timeouts razoáveis para que backends lentos não bloqueiem os workers do Nginx:
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 16k;
Terminação SSL com Let’s Encrypt
Terminação SSL significa que o Nginx gerencia o handshake TLS e encaminha HTTP simples para os backends na rede interna — sem sobrecarga de TLS nos servidores de aplicação individuais.
Instale o Certbot com o plugin para Nginx:
sudo apt install certbot python3-certbot-nginx -y
Obtenha e instale um certificado (o Certbot modifica seu bloco server automaticamente):
sudo certbot --nginx -d app.exemplo.com -d www.app.exemplo.com
O Certbot cria um timer systemd que renova os certificados automaticamente antes de expirarem:
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
Algoritmos de Balanceamento de Carga
Para balancear a carga entre vários backends, substitua o destino único de proxy_pass por um bloco upstream:
upstream app_cluster {
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Round-Robin (Padrão)
Nenhuma diretiva necessária. O Nginx distribui as requisições sequencialmente entre todos os servidores upstream. Adicione pesos para direcionar mais tráfego a nós mais potentes:
upstream app_cluster {
server 10.0.0.10:3000 weight=3;
server 10.0.0.11:3000 weight=1;
server 10.0.0.12:3000 weight=1;
}
Menos Conexões (least_conn)
O Nginx roteia cada nova requisição para o servidor upstream com menos conexões ativas. Ideal para cargas de trabalho com tempos de resposta variáveis:
upstream app_cluster {
least_conn;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
IP Hash (ip_hash)
O IP do cliente determina qual backend atende todas as requisições daquele cliente. Útil para persistência de sessão sem um armazenamento de sessão compartilhado:
upstream app_cluster {
ip_hash;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Aleatório (random)
O Nginx seleciona um backend aleatoriamente. Com o parâmetro two, escolhe dois servidores aleatoriamente e roteia para o que tem menos conexões:
upstream app_cluster {
random two least_conn;
server 10.0.0.10:3000;
server 10.0.0.11:3000;
server 10.0.0.12:3000;
}
Verificações de Saúde do Upstream
Marque servidores como backup ou defina limites de falha para que o Nginx pare de enviar tráfego para backends não disponíveis:
upstream app_cluster {
least_conn;
server 10.0.0.10:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.11:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.12:3000 backup;
}
Proxy de WebSockets
Conexões WebSocket requerem um handshake de upgrade HTTP/1.1. Adicione três diretivas a qualquer bloco location que faça proxy de tráfego WebSocket:
location /ws/ {
proxy_pass http://app_cluster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Cache com proxy_cache
O Nginx pode armazenar em cache as respostas dos backends em memória ou em disco, reduzindo drasticamente a carga do backend em endpoints cacheáveis.
Defina uma zona de cache no contexto http:
http {
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=app_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
}
Habilite o cache no bloco location:
location /api/public/ {
proxy_pass http://app_cluster;
proxy_cache app_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
}
Rate Limiting
O rate limiting protege os backends de picos de tráfego e ataques de força bruta. Defina uma zona de memória compartilhada no contexto http:
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/m;
}
Aplique a zona a um location:
location /api/ {
limit_req zone=api_limit burst=10 nodelay;
limit_req_status 429;
proxy_pass http://app_cluster;
}
Cabeçalhos de Segurança
Adicione cabeçalhos de segurança no bloco server:
server {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;
server_tokens off;
}
HTTP/2 e HTTP/3
Ative HTTP/2 na diretiva listen:
listen 443 ssl http2;
Para HTTP/3 (Nginx 1.25+):
listen 443 ssl http2;
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400' always;
Monitoramento com stub_status
Ative o módulo stub_status para expor métricas de conexão em tempo real:
server {
listen 127.0.0.1:8080;
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
}
curl http://127.0.0.1:8080/nginx_status
Comparação: Nginx vs. Alternativas
| Recurso | Nginx | HAProxy | Traefik | Caddy |
|---|---|---|---|---|
| Suporte de protocolos | HTTP, HTTPS, TCP, UDP | HTTP, HTTPS, TCP | HTTP, HTTPS, TCP, gRPC | HTTP, HTTPS |
| Algoritmos de balanceamento | RR, LC, IP hash, random | RR, LC, source, URI | RR, WRR | RR, LC |
| Health checks ativos | Apenas Nginx Plus | Sim (nativo) | Sim (nativo) | Sim (nativo) |
| SSL automático (ACME) | Via Certbot | Via Certbot | Nativo | Nativo |
| Cache integrado | Sim | Não | Não | Não |
| HTTP/3 | 1.25+ (experimental) | Não | Não | Sim |
| Melhor para | Web + proxy + cache | LB TCP/HTTP puro | Ingress no Kubernetes | SSL automático simples |
Cenário Real: Balanceamento de Carga de um Cluster Node.js com SSL
Você tem uma API Node.js de produção executando três processos PM2 no mesmo host (portas 3001, 3002, 3003) e quer expô-los como api.exemplo.com via HTTPS com afinidade de sessão, rate limiting no endpoint de autenticação e suporte a WebSocket.
upstream node_api {
ip_hash;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
limit_req_zone $binary_remote_addr zone=auth_limit:5m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=60r/m;
server {
listen 443 ssl http2;
server_name api.exemplo.com;
ssl_certificate /etc/letsencrypt/live/api.exemplo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.exemplo.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
server_tokens off;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://node_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/auth/ {
limit_req zone=auth_limit burst=3 nodelay;
limit_req_status 429;
proxy_pass http://node_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ws/ {
proxy_pass http://node_api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3600s;
}
}
server {
listen 80;
server_name api.exemplo.com;
return 301 https://$host$request_uri;
}
Armadilhas e Casos Especiais
A barra final em proxy_pass importa. proxy_pass http://backend; preserva o URI completo incluindo o prefixo /api/. proxy_pass http://backend/; remove o prefixo do location e pode causar erros 404 difíceis de diagnosticar.
Não use ip_hash se tiver uma CDN na frente do Nginx. Todo o tráfego da CDN parece vir de um pequeno conjunto de IPs, então o ip_hash enviará todo esse tráfego para um único backend.
Conexões longas e SSE requerem timeouts maiores. Conexões Server-Sent Events e long-polling ficam abertas indefinidamente. Ajuste proxy_read_timeout ao intervalo de heartbeat da sua aplicação mais uma margem.
proxy_buffering e streaming. Se o seu backend transmite uma resposta em streaming (SSE, chunked transfer), defina proxy_buffering off naquele location. Caso contrário o Nginx armazena a resposta completa no buffer antes de enviar.
Solução de Problemas
502 Bad Gateway. O backend não está em execução ou não está ouvindo na porta configurada. Verifique: sudo systemctl status sua-app, ss -tlnp | grep 3000.
504 Gateway Timeout. O backend está respondendo muito lentamente. Aumente proxy_read_timeout ou investigue a performance do backend.
Conexões WebSocket caem após 60 segundos. O proxy_read_timeout padrão do Nginx é 60 segundos. Aumente para locations de WebSocket.
Cache não funciona. Certifique-se de que proxy_cache_path está definido no contexto http, que o diretório existe e tem permissão de escrita para o usuário nginx, e que proxy_cache está configurado no bloco location correto.
Resumo
O Nginx como proxy reverso e balanceador de carga fornece uma camada de tráfego de nível produção sem infraestrutura adicional. Pontos principais:
- Sempre defina
X-Forwarded-For,X-Forwarded-ProtoeHostem cada location de proxy - Use
certbot --nginxpara provisionar certificados SSL sem downtime e com renovação automática - Escolha
least_connpara APIs,ip_hashpara persistência de sessão erandom two least_connpara grandes pools de backends - Marque os backends com
max_failsefail_timeoutpara que o Nginx remova servidores não disponíveis automaticamente - Use
proxy_http_version 1.1com os cabeçalhos Upgrade/Connection para proxy de WebSockets - Ative
proxy_cachepara endpoints públicos elimit_req_zonepara proteger rotas de autenticação - Ative
http2na diretiva listen para multiplexação; avaliequicno Nginx 1.25+
Artigos Relacionados
- Como: Compilar sua própria versão do NginX
- Fail2Ban: Proteja seu servidor Linux de ataques de força bruta
- Como configurar o firewall UFW no Ubuntu Server: Guia completo
- Como passar ao Nginx o IP correto do cliente usando um proxy reverso Varnish
- Lista de verificação de segurança para servidores Linux: 20 passos essenciais