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

RecursoNginxHAProxyTraefikCaddy
Suporte de protocolosHTTP, HTTPS, TCP, UDPHTTP, HTTPS, TCPHTTP, HTTPS, TCP, gRPCHTTP, HTTPS
Algoritmos de balanceamentoRR, LC, IP hash, randomRR, LC, source, URIRR, WRRRR, LC
Health checks ativosApenas Nginx PlusSim (nativo)Sim (nativo)Sim (nativo)
SSL automático (ACME)Via CertbotVia CertbotNativoNativo
Cache integradoSimNãoNãoNão
HTTP/31.25+ (experimental)NãoNãoSim
Melhor paraWeb + proxy + cacheLB TCP/HTTP puroIngress no KubernetesSSL 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-Proto e Host em cada location de proxy
  • Use certbot --nginx para provisionar certificados SSL sem downtime e com renovação automática
  • Escolha least_conn para APIs, ip_hash para persistência de sessão e random two least_conn para grandes pools de backends
  • Marque os backends com max_fails e fail_timeout para que o Nginx remova servidores não disponíveis automaticamente
  • Use proxy_http_version 1.1 com os cabeçalhos Upgrade/Connection para proxy de WebSockets
  • Ative proxy_cache para endpoints públicos e limit_req_zone para proteger rotas de autenticação
  • Ative http2 na diretiva listen para multiplexação; avalie quic no Nginx 1.25+

Artigos Relacionados