Proxy Reverso com Nginx: Guia Prático e Seguro
Aprenda a configurar proxy reverso com Nginx, HTTPS, WebSocket, balanceamento, cabeçalhos e diagnóstico com exemplos práticos.

Configurar um proxy reverso com Nginx permite publicar uma aplicação que funciona em uma porta interna, centralizar HTTPS, encaminhar cabeçalhos e distribuir requisições entre diferentes servidores.
Para o visitante, existe apenas o domínio público; por trás dele, o Nginx decide qual serviço receberá cada conexão.
Essa arquitetura é comum em aplicações Node.js, Python, Java, PHP, containers e painéis administrativos.
Ela também cria uma fronteira útil entre a internet e o back-end, mas não deve ser tratada como proteção automática: uma configuração incorreta pode expor portas, perder o IP do cliente, quebrar WebSockets ou aceitar arquivos maiores do que o esperado.
Neste guia, você montará uma configuração funcional no Ubuntu ou Debian, entenderá cada diretiva e aprenderá a adicionar HTTPS, WebSocket, balanceamento, limites e observabilidade.
Os exemplos usam um domínio fictício e uma aplicação local; substitua esses valores pelos dados reais do seu ambiente.
O que é um proxy reverso?
Um proxy reverso recebe conexões em nome de um ou mais servidores de origem.
O cliente acessa https://app.exemplo.com, mas a aplicação pode estar ouvindo apenas em 127.0.0.1:3000.
O Nginx aceita a conexão pública, encaminha a requisição ao serviço interno e devolve a resposta ao visitante.
Ele é “reverso” porque representa o lado dos servidores. Em um proxy de saída tradicional, a ferramenta representa clientes que querem acessar a internet. No proxy reverso, quem acessa o domínio normalmente nem conhece a topologia interna ou o endereço do back-end.
O Nginx pode atuar como servidor HTTP, cache, balanceador e proxy para diferentes protocolos.
A documentação oficial de proxy reverso do Nginx mostra que requisições HTTP são encaminhadas com proxy_pass; outros tipos de aplicação usam diretivas próprias, como fastcgi_pass ou uwsgi_pass.
Proxy reverso não é sinônimo de VPN, firewall ou CDN. Esses componentes podem coexistir, mas resolvem problemas diferentes.
Também não elimina a necessidade de autenticação e autorização dentro da aplicação. Ele controla a entrada e o encaminhamento; as regras de negócio continuam no back-end.
Quando usar Nginx como proxy reverso
O cenário mais simples é publicar uma aplicação que não deve escutar diretamente nas portas 80 e 443.
O processo pode rodar como usuário sem privilégios em uma porta local, enquanto o Nginx cuida do domínio e do certificado.
- Terminação TLS: o Nginx recebe HTTPS e conversa com um serviço local ou com outro upstream protegido.
- Vários projetos no mesmo servidor: cada domínio ou subdomínio aponta para uma porta diferente.
- Balanceamento: requisições são distribuídas entre instâncias da aplicação.
- Políticas de entrada: limites de corpo, tempo, taxa e acesso ficam centralizados.
- Cache e compressão: respostas adequadas podem ser tratadas antes de chegar ao back-end.
- Implantação gradual: grupos upstream ajudam a trocar ou escalar instâncias.
Em um único site estático, usar o Nginx diretamente como servidor de arquivos pode ser mais simples. Em plataformas gerenciadas, o provedor talvez já execute um proxy e cuide do certificado.
Antes de acrescentar uma camada, confirme o problema que ela resolverá e quem será responsável por atualizações, logs e resposta a incidentes.
Se você ainda está escolhendo infraestrutura, o comparativo entre VPS e hospedagem compartilhada ajuda a entender quando o acesso administrativo necessário para configurar Nginx realmente compensa.
Como funciona o fluxo da requisição
O DNS associa o domínio ao IP público do servidor ou balanceador. O navegador abre uma conexão com esse endereço.
Para HTTPS, o Nginx apresenta o certificado e negocia a sessão TLS. Depois, seleciona o bloco server pelo domínio e o bloco location pelo caminho.
- O cliente solicita uma URL pública.
- DNS e rede conduzem a conexão ao Nginx.
- O Nginx escolhe a regra correspondente ao domínio e caminho.
proxy_passdefine o serviço de destino.- Os cabeçalhos configurados descrevem host, protocolo e cadeia de IPs.
- O back-end processa a requisição e responde ao Nginx.
- O Nginx aplica políticas de resposta e a entrega ao cliente.
Esse fluxo cria dois trechos: cliente–Nginx e Nginx–upstream. O primeiro pode estar protegido por HTTPS enquanto o segundo usa HTTP em loopback ou rede privada.
Se o upstream estiver em outra máquina, avalie também criptografia, autenticação e regras de firewall nesse trecho interno.
Pré-requisitos e instalação do Nginx
Você precisa de um servidor Linux com acesso administrativo, um domínio apontado para o IP correto e uma aplicação respondendo localmente.
Os comandos abaixo usam Ubuntu ou Debian e o pacote disponível na distribuição. Repositórios oficiais do Nginx também existem, mas exigem configuração própria e verificação de chave.
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx
Confirme a versão instalada e os módulos compilados:
nginx -v
nginx -V
Em seguida, teste o back-end sem passar pelo proxy. Se a aplicação deveria ouvir em 127.0.0.1:3000, execute:
curl -i http://127.0.0.1:3000/health
Se essa etapa falhar, o Nginx não corrigirá o serviço. Verifique processo, porta, endereço de escuta e firewall. Para uma preparação mais ampla do ambiente, veja também como configurar um servidor VPS.
Configuração básica do proxy reverso
Em instalações Debian e Ubuntu, é comum criar um arquivo em /etc/nginx/sites-available/ e habilitá-lo com um link em sites-enabled. Outras distribuições podem organizar arquivos em conf.d. Confirme o que o bloco http do seu nginx.conf inclui.

server {
listen 80;
listen [::]:80;
server_name app.exemplo.com;
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;
}
}
Salve como /etc/nginx/sites-available/app.exemplo.com e habilite:
sudo ln -s /etc/nginx/sites-available/app.exemplo.com + /etc/nginx/sites-enabled/app.exemplo.com
sudo nginx -t
sudo systemctl reload nginx
A ausência de barra no final de proxy_pass http://127.0.0.1:3000; preserva a URI da requisição nesse exemplo. A barra final passa a importar quando existe um caminho no location.
A referência do módulo ngx_http_proxy_module detalha como o trecho correspondente da URI é substituído.
Compare:
# /api/usuarios chega ao upstream como /api/usuarios
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
# /api/usuarios chega ao upstream como /usuarios
location /api/ {
proxy_pass http://127.0.0.1:3000/;
}
Essa diferença explica muitos erros 404 após a adoção do proxy. Defina se o back-end conhece o prefixo público e teste URLs com e sem subcaminhos, parâmetros e barra final.
Cabeçalhos e IP real do cliente
O upstream enxerga o Nginx como origem da conexão. Para que a aplicação conheça o domínio e o contexto público, encaminhe cabeçalhos explicitamente.
Host conserva o domínio selecionado; X-Forwarded-Proto informa se o visitante usou HTTP ou HTTPS; X-Forwarded-For mantém uma cadeia de endereços.
| Cabeçalho | Valor comum | Uso no back-end |
|---|---|---|
| Host | $host | Gerar URLs e identificar o domínio público |
| X-Real-IP | $remote_addr | Registrar o endereço visto diretamente pelo Nginx |
| X-Forwarded-For | $proxy_add_x_forwarded_for | Preservar a cadeia de proxies e cliente |
| X-Forwarded-Proto | $scheme | Indicar o protocolo público |
| X-Forwarded-Host | $host | Informar o host original quando a aplicação exige esse dado |
Não confie cegamente em cabeçalhos enviados pela internet. A aplicação deve aceitar informações de proxy apenas quando a conexão vem de proxies conhecidos.
Além disso, a porta do back-end não deve ficar exposta publicamente, pois um cliente poderia contornar o Nginx e forjar cabeçalhos.
Se existe CDN ou balanceador antes do Nginx, $remote_addr pode representar esse componente.
Nesse caso, configure o módulo Real IP somente com as redes oficiais e mantenha a lista atualizada. Nunca use uma faixa universal como fonte confiável apenas para “fazer o IP funcionar”.
Como ativar HTTPS
Antes de emitir o certificado, confirme que o DNS já aponta para o servidor e que a porta 80 responde pelo domínio.
Uma opção comum é usar Certbot com o instalador do Nginx. Siga as instruções geradas para seu sistema em certbot.eff.org, pois o método de instalação pode variar.
sudo certbot --nginx -d app.exemplo.com
O processo pode criar ou ajustar o bloco que escuta em 443 e apontar para os arquivos do certificado.
Não copie caminhos de outro servidor e não transfira chaves privadas por repositório. Depois, valide a renovação conforme o método instalado:
sudo certbot renew --dry-run
O redirecionamento de HTTP para HTTPS deve preservar host e URI:
server {
listen 80;
listen [::]:80;
server_name app.exemplo.com;
return 301 https://$host$request_uri;
}
Se o Nginx conversa com um upstream HTTPS remoto, o trabalho é diferente: avalie SNI, confiança na autoridade certificadora e verificação do certificado do upstream.
Criptografar sem verificar identidade não oferece a proteção esperada.
Proxy reverso para WebSocket
WebSocket começa como HTTP e solicita uma mudança de protocolo. Os cabeçalhos Upgrade e Connection são hop-by-hop e não seguem automaticamente para o upstream. Por isso, precisam ser configurados.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name app.exemplo.com;
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;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
}
O bloco map pertence ao contexto http, fora de server. A documentação oficial de WebSocket no Nginx também alerta que uma conexão sem dados pode ser encerrada após o tempo de leitura; pings da aplicação ou um timeout coerente evitam desconexões silenciosas.
Não aumente o valor indefinidamente sem considerar consumo de conexões.
Subdomínios, caminhos e containers
Subdomínios costumam produzir configurações mais previsíveis. api.exemplo.com pode apontar para a API, enquanto painel.exemplo.com aponta para o front-end. Cada domínio recebe seu bloco server, certificado e regras.
Publicar vários serviços no mesmo domínio por caminho também funciona, mas exige acordo sobre prefixos:
server {
server_name exemplo.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
}
Nesse exemplo, o prefixo /api/ é removido antes de chegar ao serviço da porta 8080.
Se a API espera receber o prefixo, retire a barra da URL de proxy_pass. Também verifique cookies, redirects e URLs absolutas geradas pelo framework.
Em Docker, 127.0.0.1 dentro de um container aponta para o próprio container, não para outro serviço.
Quando Nginx e aplicação compartilham uma rede do Compose, use o nome do serviço e a porta interna, como http://api:3000.
Se o Nginx roda no host, use uma porta publicada apenas em loopback quando possível. O guia Docker descomplicado explica redes, imagens e containers antes de você combinar as camadas.
Balanceamento de carga com upstream
Um grupo upstream dá nome a várias instâncias. Sem método explícito, a distribuição ocorre em round robin.
Pesos e parâmetros de falha ajudam a representar capacidades diferentes, mas não substituem monitoramento nem health checks da plataforma.

upstream app_backend {
least_conn;
server 10.0.0.11:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.12:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.13:3000 backup;
keepalive 32;
}
server {
server_name app.exemplo.com;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
least_conn prefere a instância com menos conexões ativas. backup recebe tráfego quando os servidores principais estão indisponíveis conforme os critérios configurados.
A documentação de balanceamento HTTP do Nginx apresenta métodos e diferenças entre Nginx Open Source e Nginx Plus.
A aplicação deve funcionar com múltiplas instâncias. Sessão local em memória, arquivos gravados somente em um nó ou tarefas duplicadas podem quebrar quando as requisições mudam de destino.
Externalize estado quando necessário e garanta que o deploy mantenha versões compatíveis.
Segurança e desempenho sem receitas mágicas
Não copie um bloco enorme de “hardening” sem entender o efeito. Limites inadequados interrompem uploads e relatórios; cache indevido pode servir dados privados; timeouts exagerados mantêm recursos ocupados.
Comece com o comportamento da aplicação e altere uma política por vez.
- Feche o acesso direto ao back-end: escute em loopback ou restrinja a porta à rede do proxy.
- Atualize sistema e Nginx: acompanhe avisos de segurança do fornecedor da distribuição ou do repositório usado.
- Limite corpos quando fizer sentido:
client_max_body_sizedeve refletir uploads legítimos. - Ajuste timeouts por rota: APIs rápidas, streaming e processamento longo têm perfis diferentes.
- Proteja áreas administrativas: restrição de rede pode complementar a autenticação da aplicação.
- Evite segredos no arquivo: chaves e tokens exigem permissões, rotação e um processo próprio.
- Defina logs úteis: inclua identificador de requisição e tempos sem registrar credenciais ou dados pessoais desnecessários.
Rate limiting pode reduzir abuso, mas precisa considerar usuários legítimos, NAT, CDN e IP real. Cache só deve ser ativado quando você compreende cabeçalhos, cookies, autorização e invalidação.
Para credenciais de serviços e certificados privados, consulte o guia de gerenciamento de segredos.
O Nginx pode melhorar o uso de conexões e absorver tarefas de borda, porém não torna código lento automaticamente rápido. Meça latência do cliente, tempo do proxy e tempo do upstream.
Se o gargalo está no banco ou em uma API externa, aumentar buffers pode apenas esconder o diagnóstico.
Como validar e publicar a configuração
Nunca recarregue o serviço antes de validar a sintaxe. nginx -t verifica o arquivo principal e as inclusões.
Depois de um teste bem-sucedido, reload pede ao processo mestre que carregue a nova configuração sem interromper deliberadamente as conexões existentes.
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx
Faça testes por camadas:
# Back-end direto
curl -i http://127.0.0.1:3000/health
# Domínio por HTTP
curl -I http://app.exemplo.com
# HTTPS, cabeçalhos e redirecionamentos
curl -i https://app.exemplo.com/health
# Resolver temporariamente para um IP específico
curl --resolve app.exemplo.com:443:203.0.113.10 + https://app.exemplo.com/health
O IP 203.0.113.10 é reservado para documentação; substitua pelo endereço real.
O último comando é útil antes de mudar DNS, desde que o certificado já cubra o domínio.
Mantenha a configuração em controle de versão sem incluir chaves privadas. Automatize teste, cópia, validação e reload com uma estratégia de retorno.
O artigo sobre CI/CD com segurança mostra como transformar etapas manuais em um fluxo verificável.
Erros comuns e diagnóstico
Um erro exibido pelo Nginx nem sempre nasce nele. A mensagem ao cliente, o error log, o access log e o log da aplicação precisam ser correlacionados. Comece pelo horário e por um identificador de requisição.
| Sintoma | Causa provável | Primeira verificação |
|---|---|---|
| 502 Bad Gateway | Processo parado, porta errada, permissão ou resposta inválida | curl no upstream e error log |
| 504 Gateway Timeout | Upstream não respondeu no intervalo | Tempo da aplicação, dependências e proxy_read_timeout |
| 404 apenas pelo proxy | URI reescrita pela combinação de location e proxy_pass | Caminho recebido nos logs do back-end |
| Redirecionamento infinito | Aplicação não confia no proxy ou ignora protocolo encaminhado | X-Forwarded-Proto e configuração do framework |
| WebSocket desconecta | Cabeçalhos de upgrade ausentes ou timeout | Handshake 101, logs e pings |
| 413 Request Entity Too Large | Corpo supera o limite configurado | Tamanho legítimo e client_max_body_size |
| IP sempre igual | Aplicação usa o endereço do proxy ou cadeia não confiável | Cabeçalhos e lista de proxies confiáveis |
sudo journalctl -u nginx --since "15 minutes ago"
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
sudo ss -lntp
Se o sistema usa containers, consulte também os logs do serviço e confirme a rede pelo nome correto.
Em sistemas com SELinux, uma configuração sintaticamente válida ainda pode ser impedida de conectar ao upstream por política.
Não desative controles de segurança como solução permanente; identifique a permissão necessária.
Logs isolados ajudam no primeiro diagnóstico, mas produção exige correlação.
Métricas de taxa, erros e latência, logs estruturados e traces revelam se o atraso ocorreu no proxy, aplicação, banco ou serviço externo. O guia de OpenTelemetry apresenta essa visão unificada.
Checklist de produção
- DNS aponta para o destino correto e portas 80/443 estão controladas.
- Back-end responde em health endpoint antes do proxy.
- Porta do upstream não está aberta para toda a internet.
server_name, IPv4 e IPv6 correspondem ao ambiente.- Semântica da barra em
locationeproxy_passfoi testada. - Host, protocolo e cadeia de IPs chegam corretamente à aplicação.
- HTTPS está válido e a renovação foi testada.
- WebSocket, uploads e rotas longas receberam testes próprios quando existem.
- Limites, cache e timeouts refletem requisitos reais.
nginx -tpassa antes de cada reload.- Logs do Nginx e do upstream podem ser correlacionados.
- Existe backup da configuração, controle de versão e plano de retorno.
Uma API publicada atrás do proxy ainda precisa de contrato, validação, autenticação, autorização e observabilidade. O guia de desenvolvimento de APIs complementa a parte de aplicação que não pertence ao Nginx.
Perguntas frequentes
Proxy reverso e balanceador de carga são a mesma coisa?
Não exatamente. O proxy reverso representa servidores diante dos clientes. Ele pode encaminhar tudo a um único upstream. Balanceamento é uma função adicional que distribui tráfego entre vários destinos.
Preciso expor a porta da aplicação?
Para um serviço no mesmo host, normalmente não. Faça a aplicação escutar em loopback e exponha apenas o Nginx. Em máquinas ou containers distintos, libere a porta somente para a rede e para as origens necessárias.
Nginx substitui HTTPS na aplicação?
Ele pode terminar TLS na borda. Se o upstream está no mesmo host ou em rede privada controlada, essa arquitetura pode ser adequada. Entre redes não confiáveis, considere HTTPS também até o upstream e valide o certificado.
Por que minha aplicação cria links HTTP depois de ativar HTTPS?
Geralmente o back-end não recebeu ou não confiou em X-Forwarded-Proto. Encaminhe o cabeçalho e configure o framework para confiar apenas no proxy conhecido. Não habilite confiança universal sem entender o risco.
Quando devo desativar proxy buffering?
Somente quando o comportamento da rota pede entrega imediata, como alguns fluxos de streaming ou eventos. O buffering padrão pode proteger o upstream de clientes lentos. Meça o caso real antes de usar proxy_buffering off.
É melhor usar Nginx no host ou em container?
As duas formas funcionam. No host, integração com portas, certificados e serviço do sistema pode ser direta. Em container, configuração e versão viajam com a infraestrutura. A escolha depende de operação, redes, renovação de certificados e responsabilidade da equipe.
Conclusão
Um proxy reverso com Nginx bem configurado começa simples: domínio correto, upstream acessível, proxy_pass compreendido e cabeçalhos necessários.
HTTPS, WebSocket, balanceamento e limites entram depois, conforme requisitos observáveis.
O ponto mais importante é tratar a configuração como código operacional. Valide antes do reload, teste cada camada, mantenha histórico, restrinja o back-end e monitore proxy e aplicação juntos.
Assim, o Nginx deixa de ser uma coleção de trechos copiados e se torna uma fronteira previsível para seus serviços.