HTTPS automático no Caddy: como funciona o TLS automático e como resolver falhas
O Caddy obtém e renova certificados TLS via ACME para cada domínio da sua configuração. Entenda HTTP-01, TLS-ALPN-01, wildcards com DNS-01, TLS on-demand e as falhas mais comuns.
Resposta curta: o Caddy ativa HTTPS automaticamente para qualquer endereço de site que seja um nome de domínio público. Ele solicita um certificado via ACME (Let's Encrypt ou ZeroSSL por padrão), prova o controle do domínio pelo desafio HTTP-01 ou TLS-ALPN-01 nas portas 80 e 443, redireciona HTTP para HTTPS e renova o certificado antes que expire, sem nenhuma configuração extra.
Um reverse proxy Caddy é simplesmente o Caddy terminando essa conexão HTTPS e encaminhando a requisição para um app em outra porta, container ou host com a diretiva `reverse_proxy`. Essa combinação — TLS mais proxy em poucas linhas — é o principal motivo pelo qual as pessoas o escolhem.
Reverse proxy com SSL em três linhas
Com o DNS apontando para o servidor e as portas 80 e 443 acessíveis, este Caddyfile é um reverse proxy HTTPS completo para dois hostnames. O Caddy obtém certificados para os dois nomes na inicialização, serve HTTP/1.1, HTTP/2 e HTTP/3 e repassa `X-Forwarded-For`, `X-Forwarded-Proto` e `X-Forwarded-Host` ao backend. A opção `email` é opcional, mas permite que a CA entre em contato sobre certificados expirando ou revogados.
A instalação pelo repositório apt oficial e o básico de systemd estão no guia de reverse proxy com Caddy; para containers, veja Caddy como reverse proxy no Docker. Aplique as alterações com `sudo systemctl reload caddy`.
# /etc/caddy/Caddyfile
{
email [email protected]
}
example.com, www.example.com {
reverse_proxy 127.0.0.1:8080
}Como o TLS automático do Caddy funciona por dentro
Quando o Caddy carrega uma configuração, ele reúne todos os hostnames dos endereços de site e decide quem deve emitir cada certificado. Domínios públicos vão para os emissores ACME públicos; `localhost`, endereços IP e nomes apenas internos recebem certificados da CA local do próprio Caddy (o mesmo que escrever `tls internal`). Certificados, chaves e a conta ACME ficam no diretório de dados do Caddy: `/var/lib/caddy/.local/share/caddy` no pacote apt, `/data` na imagem Docker oficial.
A renovação acontece em segundo plano bem antes do vencimento, e o Caddy faz stapling das respostas OCSP quando a CA oferece suporte. Se a emissão falhar, o Caddy tenta de novo com backoff exponencial e usa o endpoint de staging da CA nas novas tentativas para não queimar os rate limits de produção. Várias instâncias do Caddy que compartilham o mesmo armazenamento se coordenam para que só uma solicite cada certificado.
| Desafio | O que a CA verifica | Requisitos | Wildcards? |
|---|---|---|---|
| HTTP-01 | Um token servido em `http://domain/.well-known/acme-challenge/` | Porta 80 acessível pela internet | Não |
| TLS-ALPN-01 | Um certificado especial apresentado num handshake TLS | Porta 443 acessível pela internet | Não |
| DNS-01 | Um registro TXT em `_acme-challenge.domain` | Token de API do provedor de DNS e um build do Caddy com o módulo desse provedor | Sim |
Certificados wildcard com DNS-01
Certificados wildcard como `*.example.com` só podem ser emitidos pelo desafio DNS-01. O binário padrão do Caddy não inclui plugins de provedores de DNS, então você gera um build com o xcaddy (ou escolhe o provedor na página oficial de download) e fornece ao Caddy um token de API limitado à edição do DNS daquela zona. O DNS-01 também funciona quando as portas 80 e 443 não estão acessíveis pela internet, por exemplo num servidor apenas interno.
Mantenha o token fora do Caddyfile: coloque-o num arquivo de ambiente usado pela unit do systemd (`sudo systemctl edit caddy` e depois `EnvironmentFile=/etc/caddy/caddy.env` em `[Service]`) e restrinja o arquivo com `chmod 600`.
# Build Caddy with a DNS provider module (example: Cloudflare)
xcaddy build --with github.com/caddy-dns/cloudflare
# Caddyfile: one wildcard certificate for all subdomains
*.example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
@app host app.example.com
handle @app {
reverse_proxy 127.0.0.1:3000
}
handle {
respond "Unknown host" 404
}
}TLS on-demand e staging
O TLS on-demand faz o Caddy obter um certificado durante o primeiro handshake TLS para um hostname que ele ainda não conhece. Ele foi pensado para plataformas em que os clientes apontam os próprios domínios para o seu servidor. Configure sempre o endpoint `ask`: o Caddy o chama com `?domain=name` e só prossegue com uma resposta 200. Sem isso, qualquer pessoa poderia apontar nomes aleatórios para o seu IP e fazer você estourar os rate limits.
Enquanto estiver testando, mude para a CA de staging do Let's Encrypt com a opção global `acme_ca`. Os certificados de staging não são confiáveis para os navegadores, mas os limites são muito mais altos, então você pode quebrar e consertar à vontade. Ao terminar, remova a opção e, se quiser, apague os certificados de staging do diretório de dados.
{
on_demand_tls {
ask http://127.0.0.1:5555/allowed
}
}
https:// {
tls {
on_demand
}
reverse_proxy 127.0.0.1:8080
}
# Global options block for testing
{
email [email protected]
# Test against Let's Encrypt staging; remove when everything works
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}Falhas comuns de TLS no Caddy e como corrigi-las
- 01.DNS não apontado: o registro A ou AAAA está faltando, ainda aponta para um servidor antigo ou está em cache. Um registro AAAA desatualizado é uma armadilha clássica, porque a CA prefere IPv6 quando ele existe. Verifique os dois com `dig`.
- 02.Porta 80 ou 443 fechada: o firewall do host, um firewall de nuvem ou um roteador bloqueia o tráfego de entrada, e nem o HTTP-01 nem o TLS-ALPN-01 conseguem concluir. Abra 80/tcp e 443/tcp (e 443/udp para HTTP/3).
- 03.Porta já em uso: Apache, nginx ou outro container está vinculado à 80 ou à 443, e o Caddy não consegue escutar. Pare o outro serviço ou coloque-o atrás do Caddy.
- 04.Proxy de CDN na frente: um proxy no estilo "nuvem laranja" termina o TLS antes do Caddy, o que pode quebrar o TLS-ALPN-01. Use DNS-01 ou deixe o registro como DNS-only durante a emissão.
- 05.Rate limits: tentativas fracassadas repetidas ou apagar o diretório de dados fazem você atingir os limites da CA (o Let's Encrypt limita validações fracassadas por hostname por hora e certificados duplicados por semana). Corrija a causa raiz, use staging e mantenha o diretório de dados persistente.
- 06.Registro CAA: um registro CAA que só permite outra CA bloqueia a emissão. Permita `letsencrypt.org` e `sectigo.com` (usado pela ZeroSSL) ou remova a restrição.
# Does the name resolve to this server (both IPv4 and IPv6)?
dig +short A example.com
dig +short AAAA example.com
curl -4 -s https://ifconfig.me ; echo
# Are ports 80 and 443 open in the host firewall?
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
# Is something else already bound to 80/443?
sudo ss -ltnp '( sport = :80 or sport = :443 )'
# What does Caddy say?
sudo journalctl -u caddy --no-pager -n 100HTTPS também até o backend
A maioria dos backends no mesmo host fala HTTP simples em localhost, e isso está ok. Quando o upstream fica em outra máquina ou exige TLS, use um upstream `https://` e diga ao Caddy qual nome verificar e em qual CA confiar. Evite `tls_insecure_skip_verify` fora de testes rápidos, porque ele remove a proteção contra interceptação entre o proxy e o backend. Para tráfego entre servidores, um túnel WireGuard privado costuma ser mais simples do que gerenciar certificados de backend.
Num VPS NoctisNode com root completo e um endereço IPv4 dedicado, a configuração habitual é: apontar um registro A (sem AAAA, a menos que o servidor tenha IPv6) para o servidor, abrir 80 e 443 e deixar o Caddy cuidar do resto. Se você precisa encaminhar tráfego que não é HTTP, veja proxy TCP e SSH com Caddy.
example.com {
reverse_proxy https://10.0.0.5:8443 {
transport http {
tls_server_name backend.internal
tls_trust_pool file /etc/caddy/backend-ca.pem
}
}
}Perguntas frequentes
QO que é um reverse proxy Caddy?
AÉ o servidor web Caddy aceitando conexões de clientes, normalmente terminando o HTTPS, e encaminhando as requisições para um ou mais serviços de backend com a diretiva `reverse_proxy`. O Caddy obtém e renova automaticamente os certificados TLS para isso.
QO Caddy renova os certificados automaticamente?
ASim. O Caddy renova os certificados em segundo plano bem antes do vencimento e os recarrega sem reiniciar, desde que o domínio continue resolvendo para o servidor e as portas do desafio continuem acessíveis.
QPor que o Caddy não está conseguindo um certificado?
AAs causas mais comuns são registros DNS apontando para outro lugar (inclusive um registro AAAA desatualizado), portas 80 e 443 bloqueadas, outro programa usando essas portas ou rate limits após falhas repetidas. `journalctl -u caddy` mostra o erro ACME exato.
QO Caddy consegue emitir um certificado wildcard?
ASim, mas só pelo desafio DNS-01, que exige um build do Caddy com o módulo do seu provedor de DNS e um token de API para aquela zona.
QComo desativo o HTTPS automático no Caddy?
AUse um endereço de site `http://` para um único site ou defina a opção global `auto_https off`. Você também pode usar `auto_https disable_redirects` para manter os certificados, mas parar o redirecionamento de HTTP para HTTPS.