Proxy Reverso no Nginx com HTTPS Grátis (Let’s Encrypt)
|

Proxy Reverso no Nginx com HTTPS Grátis (Let’s Encrypt)

Expor cada serviço interno com seu próprio certificado autoassinado é o motivo mais comum de aviso de “conexão não é privada” em painel de monitoramento, Grafana caseiro ou app interno. A solução mais simples é colocar um Nginx na frente, terminando TLS num único lugar com certificado gratuito do Let’s Encrypt renovado sozinho. Este guia configura isso do zero, em um servidor Ubuntu/Debian, com Certbot.

Por que proxy reverso em vez de TLS em cada serviço

Manter certificado em cada aplicação individualmente significa renovar N certificados, em N formatos diferentes, alguns em serviços que nem suportam ACME nativamente (painéis de storage, dashboards internos, APIs simples). Com o Nginx como proxy reverso, o certificado existe em um lugar só, o Certbot renova automaticamente, e cada serviço interno continua rodando HTTP puro em 127.0.0.1 — sem exposição direta à internet.

Isso também simplifica firewall: só as portas 80 e 443 do Nginx ficam expostas publicamente. Os serviços de verdade (Zabbix, Grafana, uma API interna, o que for) ficam atrás, acessíveis só pelo próprio host.

Pré-requisitos

  • Servidor Ubuntu 22.04+ ou Debian 12+ com acesso root/sudo.
  • Um domínio ou subdomínio apontando via registro A/AAAA para o IP público do servidor.
  • Portas 80 e 443 liberadas no firewall (UFW, iptables ou security group do provedor de nuvem).
  • O serviço a proteger já rodando localmente, por exemplo em 127.0.0.1:8080.

Passo a passo: proxy reverso com HTTPS no Nginx

1. Instale o Nginx e o Certbot

O pacote python3-certbot-nginx é o plugin que edita a configuração do Nginx automaticamente durante a emissão do certificado — sem ele, o processo vira manual.

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx -y

2. Confirme o DNS antes de prosseguir

O Certbot valida domínio pelo desafio HTTP-01: ele publica um arquivo em /.well-known/acme-challenge/ e a Let’s Encrypt confirma acessando esse caminho pelo domínio informado. Se o DNS ainda não propagou, a emissão falha.

dig +short app.exemplo.com.br

O resultado precisa bater com o IP público do servidor.

3. Crie o bloco de servidor do proxy reverso

sudo nano /etc/nginx/sites-available/app.exemplo.com.br
server {
    listen 80;
    server_name app.exemplo.com.br;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
    }
}

Os três cabeçalhos X-Forwarded-* importam porque, sem eles, a aplicação por trás do proxy enxerga toda requisição vindo de 127.0.0.1 — logs de acesso ficam inúteis e qualquer lógica de IP na aplicação (rate limit, geolocalização) quebra.

4. Ative o site e teste a configuração

sudo ln -s /etc/nginx/sites-available/app.exemplo.com.br /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t valida a sintaxe antes de recarregar — pular esse passo é a forma mais comum de derrubar um Nginx em produção por um erro de digitação.

5. Emita o certificado com o Certbot

sudo certbot --nginx -d app.exemplo.com.br

O plugin edita o bloco criado no passo 3, adiciona o bloco listen 443 ssl com os caminhos do certificado, e pergunta se você quer redirecionar HTTP para HTTPS automaticamente — responda que sim, a menos que tenha um motivo específico para manter as duas portas ativas.

6. Confirme a renovação automática

A instalação via apt já cria um timer do systemd que roda duas vezes ao dia e renova qualquer certificado a menos de 30 dias do vencimento. Vale confirmar que ele existe e simular uma renovação sem gerar certificado de teste real:

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

7. Opcional: reforce com HSTS e cabeçalhos de segurança

Dentro do bloco server de porta 443 criado pelo Certbot, adicione:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;

O HSTS instrui o navegador a nunca mais tentar HTTP puro nesse domínio, mesmo que alguém digite a URL sem https:// — fecha a janela de um possível downgrade attack.

Por que a validade do certificado está encolhendo

Até pouco tempo, um certificado Let’s Encrypt durava 90 dias. A entidade já anunciou o plano de reduzir esse prazo para 45 dias até 2028, e em janeiro de 2026 tornou geral a disponibilidade de certificados de curtíssima duração — apenas 160 horas, pouco mais de 6 dias, como opção opt-in via perfil shortlived no cliente ACME. A lógica é reduzir o tempo que uma chave comprometida continua válida e diminuir a dependência de sistemas de revogação, que historicamente são lentos e mal suportados pelos navegadores.

Na prática, isso significa que renovação manual deixou de ser opção viável há tempos, e vai ficar ainda menos viável. Um proxy reverso com Certbot configurado como acima já renova sozinho; o único cuidado real é garantir que o timer do systemd está ativo e que ninguém desabilitou o cron por engano numa limpeza de servidor.

Erros comuns

  • Porta 80 bloqueada no firewall. O desafio HTTP-01 do Certbot precisa da porta 80 aberta, mesmo que o objetivo final seja servir tudo em 443.
  • DNS não propagado. Emitir certificado antes do registro A resolver globalmente derruba a validação. Espere o dig confirmar.
  • Bloco default_server concorrendo. Se o Nginx ainda serve a página padrão em 0.0.0.0:80, ela pode capturar a requisição do desafio ACME antes do bloco correto. Desative o site padrão em sites-enabled se isso acontecer.
  • Aplicação interna escutando em 0.0.0.0 em vez de 127.0.0.1. Isso expõe o serviço direto, sem TLS, para quem souber a porta — o proxy reverso só protege o que está atrás dele se o serviço não estiver acessível por fora também.

Perguntas frequentes

Preciso manter a porta 80 aberta depois de emitir o certificado?
Sim. As renovações automáticas usam o mesmo desafio HTTP-01, então a porta 80 continua necessária enquanto o certificado existir.

Funciona atrás de CGNAT ou IP dinâmico?
Não diretamente — o Certbot precisa alcançar o servidor pelo domínio público. Nesses casos, use um serviço de DNS dinâmico ou um túnel reverso até um ponto com IP público fixo.

Dá para proteger vários subdomínios com um único bloco?
Sim, repetindo -d na chamada do Certbot (-d app.exemplo.com.br -d api.exemplo.com.br) ou usando um certificado wildcard, que exige desafio DNS-01 em vez de HTTP-01.

O certificado renova para sempre sem eu fazer nada?
Enquanto o timer do systemd estiver ativo e o DNS continuar apontando para o servidor, sim. Vale checar systemctl status certbot.timer de vez em quando, principalmente após migrações de servidor.

A renovação derruba o serviço por trás do proxy?
Não. O Certbot recarrega o Nginx (reload, não restart) após renovar, o que aplica o novo certificado sem derrubar conexões em andamento.

Conclusão

Um proxy reverso com Nginx e Certbot resolve de uma vez o problema de TLS para qualquer número de serviços internos, com renovação automática que só tende a ficar mais frequente conforme os prazos de validade encolhem. O investimento inicial é os sete passos acima; a manutenção depois disso é praticamente zero.

Gostou? Compartilhe.

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *