Instalar Let's Encrypt no Nginx Ubuntu: HTTPS grátis em 10 minutos
Aprenda a instalar Let's Encrypt no Nginx Ubuntu 24.04 com Certbot, renovação automática e HTTPS validado A+ no SSL Labs.
Certificados SSL/TLS deixaram de ser luxo há muito tempo — Chrome marca qualquer site em HTTP como “Não seguro” desde 2018, navegadores móveis nem deixam fazer POST sem TLS, e o Google penaliza HTTP no ranking de busca. Let’s Encrypt resolveu o problema de custo (certificados gratuitos) e de operação (renovação automática), mas a configuração correta no Nginx ainda derruba muita gente por causa de detalhes de DNS, ordem dos comandos e cipher suites desatualizadas.
Este tutorial mostra como instalar e configurar Let’s Encrypt no Nginx rodando em Ubuntu 24.04 LTS, do zero até um grade A+ no SSL Labs. Cobrimos a parte que costuma ser pulada: validação prévia do DNS, redirect HTTP→HTTPS sem loop, renovação testada com --dry-run, e hook de reload pro Nginx pegar o cert novo sem intervenção manual.
Tempo estimado: 10 a 15 minutos se o DNS já está propagado. Se você acabou de criar o registro A, espere a propagação completar antes de começar — caso contrário o desafio HTTP-01 falha e você gasta quota de rate limit sem necessidade.
Pré-requisitos
Servidor Ubuntu 24.04 LTS com acesso sudo, Nginx instalado e rodando, um domínio registrado apontando pro IP público do servidor (registro A no DNS), portas 80 e 443 abertas no firewall e propagação de DNS completa. Sem isso, o Certbot falha no desafio HTTP-01.
Ubuntu 24.04 LTS Nginx 1.24+ 80 e 443 (TCP) ~50 MB para certbot Antes de continuar, valide que seu domínio resolve pro IP correto. Rode dig +short seudominio.com.br na sua máquina local — o resultado precisa ser o IP público do servidor. Se vier vazio ou um IP diferente, o problema está no DNS e nenhum passo deste tutorial vai funcionar até consertar lá.
Instalando o Certbot
O Certbot é o cliente oficial da Let’s Encrypt e o jeito recomendado de emitir e renovar certificados. Ubuntu 24.04 traz uma versão no apt, mas a Electronic Frontier Foundation recomenda instalar via snap pra garantir atualizações automáticas — o cliente evolui rápido e versões antigas podem quebrar com mudanças no protocolo ACME.
Atualize o índice de pacotes e instale o snapd se ainda não tiver:
sudo apt update
sudo apt install -y snapdEm Ubuntu 24.04 LTS, snapd já vem pré-instalado na maioria das imagens de servidor, mas em VPS minimalistas pode estar ausente. O comando é idempotente — não causa problema rodar de novo.
Remova qualquer versão antiga do Certbot que esteja instalada via apt, pra evitar conflito:
sudo apt remove -y certbot python3-certbot-nginxSe o apt responder “Package ‘certbot’ is not installed”, ignora — significa que não tinha versão antiga pra remover.
Instale o Certbot via snap e crie o link simbólico pra que o comando fique disponível no PATH:
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotA flag --classic é necessária porque o Certbot precisa acessar diretórios fora do confinamento padrão do snap (especificamente /etc/letsencrypt e /etc/nginx).
Confirme a versão instalada:
certbot --versionVocê deve ver algo como certbot 2.x.x. Versões 1.x ainda funcionam mas estão obsoletas — se aparecer 1.x, refaça os passos anteriores.
Configurando o Nginx pro desafio HTTP-01
Let’s Encrypt valida posse do domínio via um arquivo que precisa ser servido em http://seudominio.com.br/.well-known/acme-challenge/. O plugin --nginx do Certbot edita seu vhost automaticamente, mas pra isso precisa de um server block válido escutando na porta 80 com o server_name correto.
Crie um vhost básico em /etc/nginx/sites-available/seudominio.com.br:
server {
listen 80;
listen [::]:80;
server_name seudominio.com.br www.seudominio.com.br;
root /var/www/seudominio.com.br;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}Troque seudominio.com.br pelo seu domínio real em todas as ocorrências. Se você está hospedando uma aplicação dinâmica (Node, PHP-FPM, Python), o location / muda — mas mantenha o server_name exato.
Ative o vhost criando o symlink em sites-enabled e teste a sintaxe:
sudo ln -s /etc/nginx/sites-available/seudominio.com.br /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxO nginx -t reporta erros de configuração sem aplicar — sempre rode antes do reload. Se aparecer erro de symlink já existir (caso esteja repetindo o tutorial), remova com sudo rm /etc/nginx/sites-enabled/seudominio.com.br antes de recriar.
Se você tem um vhost default na porta 80 (geralmente /etc/nginx/sites-enabled/default), garanta que ele NÃO captura requisições pro seu domínio. O Nginx escolhe vhost por server_name, mas se nenhum bater ele cai no default_server. Remova o default ou ajuste o server_name _ pra um valor que nunca casa.
Emitindo o certificado
Com Nginx servindo o domínio na porta 80, o Certbot consegue completar o desafio. O comando abaixo emite o certificado, instala as diretivas SSL no vhost e configura redirect HTTP→HTTPS automaticamente.
Rode o Certbot com o plugin nginx:
sudo certbot --nginx -d seudominio.com.br -d www.seudominio.com.brO Certbot vai perguntar:
- E-mail pra notificações de expiração (use um e-mail que você lê — é o canal de alerta se a renovação falhar)
- Aceitação dos termos da Let’s Encrypt (responda
Y) - Se quer compartilhar e-mail com a EFF (opcional, responda
Nse preferir privacidade) - Se quer redirecionar tráfego HTTP pra HTTPS (responda
2pra ativar — recomendado)
Após alguns segundos, o cert é emitido e o Nginx já está servindo HTTPS.
Verifique que o certificado foi instalado abrindo https://seudominio.com.br no navegador. Você deve ver o cadeado verde sem warnings. Se o navegador reclamar de cert inválido, confira:
- O
server_nameno vhost bate exatamente com o domínio acessado - Você incluiu
www.no Certbot se acessa via www - O DNS já propagou (cheque com
dig)
Antes de emitir cert real, rode com --staging pra validar a config sem queimar rate limit. O cert staging não é confiável pelo navegador (vai dar warning) mas confirma que o desafio funciona. Depois remova o --staging e rode de novo pra emitir o cert de produção.
Configurando renovação automática
Certificados Let’s Encrypt expiram em 90 dias. O snap do Certbot já cria um timer systemd que tenta renovar duas vezes por dia — mas é prudente validar que está funcionando e adicionar o hook de reload do Nginx.
Confirme que o timer systemd do Certbot está ativo:
sudo systemctl list-timers | grep certbotVocê deve ver snap.certbot.renew.timer listado com próxima execução agendada. Se não aparecer, ative manualmente:
sudo systemctl enable --now snap.certbot.renew.timerConfigure o hook de deploy pra recarregar o Nginx após cada renovação bem-sucedida:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
echo '#!/bin/bash
systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shSem esse hook, o cert renovado fica em disco mas o Nginx continua servindo o antigo até o próximo restart manual. Com o hook, a operação é totalmente sem intervenção.
Teste a renovação em modo dry-run pra validar que tudo funciona sem mexer no cert real:
sudo certbot renew --dry-runOutput esperado: Congratulations, all simulated renewals succeeded. Se der erro, leia a mensagem com atenção — geralmente é firewall fechado na porta 80 ou DNS quebrado.
Verificação final
Com tudo configurado, valide o nível de segurança do seu HTTPS no SSL Labs. Acesse https://www.ssllabs.com/ssltest/analyze.html?d=seudominio.com.br e aguarde 1-2 minutos pra análise completar. O grade esperado é A. Pra chegar em A+, edite seu vhost e adicione na seção server (já existente, criada pelo Certbot) os headers de segurança:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
Recarregue o Nginx com sudo systemctl reload nginx e refaça o teste no SSL Labs.
A diretiva preload no HSTS adiciona seu domínio na lista do Chrome embedada no binário do navegador. Reverter leva meses. Só ative se você tem certeza de que TODO subdomínio do seu site vai servir HTTPS pra sempre. Em ambiente de testes, omita preload e ajuste max-age pra valor menor (ex: 300 segundos).
Resolução de problemas
Erro “Connection refused” no desafio HTTP-01
Significa que o Certbot não conseguiu acessar a porta 80 do seu servidor. Confirme com sudo ufw status se o firewall está liberando a porta, e cheque se algum outro serviço (Apache, outro Nginx) está conflitando. Mate o conflito com sudo ss -tlnp | grep :80.
Erro “DNS problem: NXDOMAIN looking up A”
DNS ainda não propagou ou o registro A não existe. Confirme localmente com dig +short seudominio.com.br @8.8.8.8 (usa o DNS público da Google). Se vier vazio, vá no painel do seu registrador e crie o registro A apontando pro IP do servidor.
Cert renovou mas navegador ainda mostra o antigo
Confirme que o hook de reload está executável e funcionando. Force renovação ignorando o cooldown com sudo certbot renew --force-renewal e veja o output. Se o hook não rodar, o problema está em /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh — confira permissões com ls -la.
Próximos passos
Com HTTPS rodando, considere os próximos hardenings: configurar OCSP Stapling pra reduzir latência da verificação de revogação, adicionar Content Security Policy pra mitigar XSS, e ativar HTTP/2 ou HTTP/3 no Nginx (já vem habilitado por padrão na linha 1.25+). Pra produção séria, monitore a expiração do certificado com Uptime Robot ou similar — alerta independente do cron de renovação.
Se você está colocando uma aplicação crítica em produção, uma VPS Hostini entrega snapshots automáticos, IPv6 nativo e firewall de rede já configurado pra reduzir o caminho entre apt install nginx e o site no ar com grade A+.
Perguntas frequentes
Posso emitir certificado Let's Encrypt sem ter um domínio?
Não. Let's Encrypt valida posse via desafio HTTP-01 ou DNS-01, e ambos exigem um nome registrado apontando pro servidor. Pra desenvolvimento local use mkcert ou um CA interno; pra IPs públicos sem domínio não há autoridade pública gratuita que emita certificado.
Qual a diferença entre Certbot --nginx e --webroot?
O plugin --nginx edita seu nginx.conf automaticamente pra inserir as diretivas ssl_certificate e fazer o desafio. O --webroot só coloca o arquivo de validação em um diretório existente e te deixa configurar o vhost manualmente. Use --nginx em hosts simples e --webroot quando seu Nginx já está em produção com config customizada que você não quer que o Certbot toque.
Quantos certificados posso emitir por domínio?
Let's Encrypt aplica rate limit de 50 certificados por domínio registrado por semana e 5 certificados duplicados por semana. Se você está testando, use o ambiente staging (--staging) que tem limites bem maiores e emite certs não-confiáveis pelo browser — perfeito pra validar a config sem queimar quota.
Por que meu certificado renovou mas o Nginx ainda mostra o antigo?
O Certbot atualiza os arquivos em /etc/letsencrypt/live/ mas o Nginx mantém o cert antigo em memória até receber sinal de reload. O hook deploy --deploy-hook 'systemctl reload nginx' resolve isso. Sem ele, você só vê o novo cert depois de um reload manual ou restart do serviço.
É seguro abrir a porta 80 só pro Certbot e fechar depois?
Não recomendado. A renovação automática a cada 60 dias precisa da porta 80 pra completar o desafio HTTP-01. Deixe a 80 aberta mas configure um redirect 301 permanente pra 443 — isso atende o Certbot e força todo tráfego pra HTTPS sem expor conteúdo em texto claro.
Posso usar Let's Encrypt em ambiente de produção crítica?
Sim. Let's Encrypt emite mais de 350 milhões de certificados ativos pra sites como Reddit, Shopify e parte da CDN da Cloudflare. O catch é operacional: você precisa garantir que a renovação automática funciona (testar com --dry-run) e monitorar expiração com alertas, porque um certificado expirado quebra o site silenciosamente do ponto de vista do visitante.