Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Nginx como Proxy para Node.js

Atualizado em: 22 de agosto de 2026

Rack de servidores processando fluxos de dados no Node.js

Usar o Nginx como proxy para Node.js permite colocar uma camada especializada em HTTP, TLS, arquivos estáticos, compressão, cache e balanceamento diante da aplicação. O Node.js continua responsável pela lógica de negócio, enquanto o Nginx aceita conexões públicas, encaminha requisições e aplica políticas operacionais.

Essa arquitetura facilita certificados, múltiplos processos, limites de upload, timeouts e deploys sem expor diretamente a porta da aplicação. Porém, configurações incorretas podem remover o IP real, quebrar WebSocket, duplicar compressão ou permitir spoofing de headers encaminhados.

Neste guia, você aprenderá a configurar proxy_pass, headers, TLS, WebSocket, SSE, balanceamento, health checks, timeouts, cache, segurança, logs e graceful shutdown.

O que é um proxy reverso?

Um proxy reverso recebe a requisição do cliente e a encaminha para um servidor interno. A documentação oficial do Nginx sobre reverse proxy apresenta diretivas e exemplos. O RFC 7239 sobre Forwarded descreve informações de proxy em HTTP.

Para TLS na aplicação, consulte HTTPS e TLS no Node.js. Para gerenciamento de processos, veja PM2 em produção com Node.js.

Arquitetura básica

Internet
   ↓
Nginx :443
   ↓
Node.js :3000

A porta 3000 pode ficar disponível apenas no loopback ou em rede privada.

Servidor Node.js

const http = require('node:http');

const server = http.createServer((req, res) => {
  res.setHeader('content-type', 'application/json');
  res.end(JSON.stringify({ status: 'ok' }));
});

server.listen(3000, '127.0.0.1');

Vincular ao loopback impede acesso direto pela rede externa no mesmo host.

Configuração mínima do Nginx

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

Valide antes de recarregar:

sudo nginx -t
sudo systemctl reload nginx

Headers encaminhados

location / {
    proxy_pass http://127.0.0.1:3000;

    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;
}

Esses headers ajudam a aplicação a conhecer host, protocolo e IP original.

Não confie em headers externos

O Nginx deve substituir, não apenas preservar, os headers relevantes. Se a aplicação é acessível diretamente, um cliente pode forjar X-Forwarded-For.

Trust proxy no Express

app.set('trust proxy', 'loopback');

Evite true sem entender quantos proxies existem. Uma configuração ampla pode fazer a aplicação confiar em IP e protocolo enviados pelo cliente.

Host original

O header Host pode influenciar geração de links, redirects e seleção de tenant. Valide nomes aceitos e não gere URLs absolutas com host arbitrário.

TLS no Nginx

server {
    listen 443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

Proteja a chave privada e automatize renovação de certificados.

Redirecionando HTTP para HTTPS

server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}

Use HSTS somente depois de confirmar que todos os subdomínios necessários suportam HTTPS.

Timeouts

location / {
    proxy_connect_timeout 5s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    send_timeout 30s;

    proxy_pass http://127.0.0.1:3000;
}

Alinhe timeouts entre cliente, Nginx e Node.js. Um proxy que espera 60 segundos diante de uma aplicação com prazo de 5 pode manter conexões inúteis.

Uploads

client_max_body_size 10m;

Esse limite rejeita corpos grandes antes de chegarem ao Node.js. A aplicação ainda precisa validar tamanho real, tipo e conteúdo.

Buffering

Por padrão, o Nginx pode armazenar respostas do upstream em buffers. Isso protege o Node.js de clientes lentos, mas pode atrasar streaming.

proxy_buffering on;

Server-Sent Events

Para SSE, desative buffering na rota:

location /events {
    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 1h;
}

Consulte Server-Sent Events com Node.js.

WebSocket

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    location /socket {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

Sem Upgrade e Connection, o handshake pode falhar.

Veja WebSocket com Node.js.

Keep-alive com upstream

upstream node_backend {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://node_backend;
    }
}

Conexões reutilizadas reduzem handshakes entre Nginx e aplicação.

Balanceamento entre processos

upstream node_backend {
    least_conn;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
}

least_conn envia novas requisições ao servidor com menos conexões ativas.

Round robin

Sem diretiva adicional, o Nginx usa round robin. Funciona bem quando instâncias possuem capacidade semelhante e requisições têm duração parecida.

Estado de sessão

Não mantenha sessão apenas na memória de uma instância. Use cookies assinados, Redis ou banco compartilhado. Assim, qualquer processo atende a próxima requisição.

Sticky sessions

Afinidade pode ser necessária em aplicações legadas, mas reduz flexibilidade e distribuição. Para WebSocket, a conexão permanece na mesma instância depois do upgrade, sem precisar reescolher durante a sessão.

Health endpoint

app.get('/health/live', (req, res) => {
  res.status(200).json({ status: 'ok' });
});

Uma rota de readiness pode verificar dependências críticas com timeout curto.

Consulte Health checks no Node.js.

Falha de upstream

O Nginx retorna 502 quando não consegue conectar ao Node.js. Logs devem diferenciar falha de conexão, timeout e resposta inválida.

proxy_next_upstream

proxy_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries 2;

Retries automáticos são mais seguros em GET e outras operações idempotentes. Não repita POST de pagamento sem chave de idempotência.

Veja Idempotência em APIs Node.js.

Graceful shutdown

Durante deploy, a instância deve parar de receber trabalho, concluir conexões e encerrar. Consulte Graceful Shutdown no Node.js.

Removendo uma instância

Em uma implantação simples:

  1. remova ou marque o upstream;
  2. recarregue o Nginx;
  3. aguarde conexões terminarem;
  4. encerre o processo;
  5. suba a nova versão;
  6. recoloque no pool.

Reload do Nginx

nginx -s reload ou systemd recarregam configuração sem derrubar conexões existentes, desde que a configuração seja válida.

Arquivos estáticos

location /assets/ {
    root /srv/app/public;
    try_files $uri =404;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Use nomes com hash para validade longa.

Compressão no Nginx

gzip on;
gzip_types application/json text/css application/javascript;
gzip_min_length 1024;

Se o Nginx comprime, desative compressão duplicada no Node.js.

Consulte Compressão HTTP no Node.js.

Cache de proxy

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m;

location /public-api/ {
    proxy_cache api_cache;
    proxy_cache_valid 200 60s;
    proxy_pass http://node_backend;
}

Cache apenas respostas públicas. Respostas autenticadas exigem regras explícitas.

Cache-Control e ETag

O Node.js pode definir Cache-Control e ETag, e o Nginx respeitar ou ajustar. Consulte ETag e Cache HTTP no Node.js.

CORS

Centralizar CORS no Nginx pode funcionar, mas regras dinâmicas e autenticação costumam pertencer à aplicação. Evite configurar em ambos os lugares com valores divergentes.

Headers de segurança

Nginx pode adicionar:

add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy no-referrer always;

Content Security Policy costuma depender da aplicação e de nonces. Veja Helmet e CSP no Node.js.

Ocultando versão

server_tokens off;

Isso reduz informação exposta, mas não substitui atualizações.

Limite de conexões

Use limites no Nginx e na aplicação para evitar que um cliente monopolize recursos. Rate limiting pode ser aplicado por IP ou chave, considerando proxies confiáveis.

Logs de acesso

log_format main '$remote_addr $request_id $request_method $uri '
                '$status $request_time $upstream_response_time';

Não registre query strings com tokens ou dados pessoais.

ID de requisição

O Nginx pode gerar ou encaminhar um ID:

proxy_set_header X-Request-ID $request_id;

A aplicação inclui o mesmo valor em logs e resposta, após validação de formato.

Logs do Node.js

Use logs estruturados em stdout. O gerenciador de processos ou agente coleta. Não faça o Nginx e o Node.js registrarem corpos completos.

Endereço real em containers

Em Docker ou Kubernetes, o upstream pode ser um nome DNS interno. Considere resolução, mudança de IP e política de atualização do Nginx.

Docker Compose

upstream node_backend {
    server app:3000;
}

O serviço app é resolvido pela rede do Compose.

Kubernetes

Em Kubernetes, um Ingress Controller frequentemente substitui um Nginx instalado manualmente no pod. Mantenha a aplicação independente da implementação do proxy.

HTTP/2

O cliente pode usar HTTP/2 com Nginx, enquanto o upstream usa HTTP/1.1. Isso é comum e simplifica a aplicação.

Timeout do Node.js

Configure requestTimeout, headersTimeout e keep-alive de forma compatível com o proxy. Valores incoerentes causam resets.

Observabilidade

Monitore:

  • status 499, 502, 503 e 504;
  • tempo total;
  • tempo de upstream;
  • conexões ativas;
  • fila;
  • bytes enviados;
  • cache hit;
  • recarregamentos com erro.

Testes

Cubra:

  • HTTP para HTTPS;
  • IP real;
  • Host permitido;
  • upload acima do limite;
  • timeout;
  • WebSocket;
  • SSE;
  • instância indisponível;
  • recarregamento;
  • headers de cache.

Erros comuns

  • Trust proxy amplo: cliente forja IP e HTTPS.
  • Porta Node pública: regras do Nginx são contornadas.
  • WebSocket sem Upgrade: conexão falha.
  • Buffering em SSE: eventos atrasam.
  • Timeouts desalinhados: conexões resetam.
  • Compressão dupla: CPU e resposta são prejudicadas.
  • Cache de conteúdo privado: dados vazam.

Boas práticas

  • Mantenha Node.js em rede privada.
  • Substitua headers encaminhados.
  • Configure trust proxy restrito.
  • Alinhe timeouts.
  • Defina limites de corpo.
  • Trate WebSocket e SSE separadamente.
  • Use graceful shutdown.
  • Centralize compressão.
  • Valide configuração antes do reload.
  • Monitore upstreams e status.

Conclusão

Usar o Nginx como proxy para Node.js separa responsabilidades: o proxy gerencia conexões públicas, TLS, arquivos, compressão e balanceamento, enquanto a aplicação executa regras de negócio.

O resultado é mais confiável quando headers, timeouts, buffering, cache e confiança em proxies são configurados explicitamente. Com a porta do Node.js protegida, logs correlacionados e deploy gradual, o Nginx oferece uma camada operacional robusta sem esconder falhas da aplicação.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita