Caddy 2: Web Server com HTTPS Automático via ACME para PME
Neste artigo
Introdução: Caddy vs Nginx e HTTPS automático
O Caddy 2 é um web server open-source escrito em Go que se destacou por uma funcionalidade única: HTTPS automático por defeito. Enquanto o Nginx exige configuração manual de certificados, renovação agendada e ajuste fino de parâmetros TLS, o Caddy obtém, instala e renova certificados automaticamente usando o protocolo ACME. Para pequenas e médias empresas (PME) que não têm um administrador de sistemas dedicado, isto reduz drasticamente a complexidade operacional.
O Caddy 2 foi reescrito do zero face à versão 1, introduzindo uma arquitectura modular via plugins, um formato de configuração unificado (Caddyfile para uso simples, JSON para configuração programática) e suporte para HTTP/3 nativo. A comparação directa com Nginx resume-se a três pontos:
| Característica | Caddy 2 | Nginx |
|---|---|---|
| HTTPS automático | Sim, por defeito | Requer Certbot + cron |
| Configuração | Caddyfile (sintaxe simples) | nginx.conf (verboso) |
| HTTP/3 | Nativo | Experimental (quic) |
| Renovação TLS | Automática, transparente | Certbot timer manual |
| Linguagem | Go (binário único) | C (dependências SO) |
ℹ Quando escolher Caddy
O Caddy é ideal para PME que precisam de servir sites com HTTPS sem querer gerir certificados manualmente. Para infraestruturas com centenas de virtual hosts ou requisitos de performance extrema (milhares de requests por segundo), o Nginx mantém vantagem em tuning fino.
Instalar Caddy em Linux
A instalação oficial usa repositórios de pacotes mantidos pelos developers do Caddy. Os comandos abaixo cobrem Debian/Ubuntu, que é a distribuição mais comum em servidores PME.
Debian/Ubuntu:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Fedora/RHEL:
sudo dnf install 'dnf-command(copr)'
sudo dnf copr enable @caddy/caddy
sudo dnf install caddy
O pacote instala o binário caddy, o serviço systemd e o ficheiro de configuração em /etc/caddy/Caddyfile. Após a instalação, activar e iniciar o serviço:
sudo systemctl enable --now caddy
sudo systemctl status caddy
Por defeito, o Caddy escuta nos portos 80 (HTTP) e 443 (HTTPS). Verificar com curl:
curl -I http://localhost
# HTTP/1.1 200 OK
# Server: Caddy
⚠ Abrir portos na firewall
Se o servidor estiver atrás de um firewall (ufw, firewalld, iptables), abrir os portos 80 e 443 antes de continuar. O Caddy precisa do porto 80 para o challenge HTTP-01 do ACME, mesmo que o site sirva apenas HTTPS.
Caddyfile: sintaxe, reverse proxy e múltiplos sites
O Caddyfile é o formato de configuração simplificada do Caddy 2. Cada bloco começa com o endereço do site e contém directivas indentadas. Um site básico que serve ficheiros estáticos:
exemplo.pt {
root * /var/www/exemplo
file_server
encode gzip zstd
}
O Caddy interpreta exemplo.pt como o hostname e activa HTTPS automaticamente. A directiva root define a raiz dos ficheiros, file_server activa o servidor de ficheiros estáticos e encode activa compressão.
Reverse proxy para uma aplicação backend (ex: Node.js, Python, PHP-FPM):
app.exemplo.pt {
reverse_proxy localhost:3000
encode gzip zstd
header {
X-Frame-Options DENY
X-Content-Type-Options nosniff
Referrer-Policy no-referrer
}
}
A directiva reverse_proxy encaminha todo o tráfego para o backend especificado, preservando cabeçalhos e IP do cliente via X-Forwarded-For. O bloco header adiciona cabeçalhos de segurança HTTP.
Múltiplos sites no mesmo Caddyfile, cada um com configuração independente:
www.exemplo.pt {
root * /var/www/exemplo
file_server
encode gzip zstd
}
api.exemplo.pt {
reverse_proxy localhost:8080 {
header_up Host {host}
}
}
blog.exemplo.pt {
root * /var/www/blog
file_server
encode gzip zstd
try_files {path} /index.html
}
Após editar o Caddyfile, validar a sintaxe e recarregar a configuração sem reiniciar o serviço:
caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
💡 Dica: reload vs restart
Usar systemctl reload caddy em vez de restart. O reload aplica a nova configuração sem quebrar ligações activas, essencial em produção.
HTTPS Automático: Let’s Encrypt, ZeroSSL e DNS challenge
O Caddy 2 gere certificados TLS automaticamente através do protocolo ACME. Por defeito, tenta obter certificados de duas autoridades de certificação (CA): Let’s Encrypt e ZeroSSL. Se uma falhar, tenta a outra automaticamente, garantindo redundância. Os certificados são renovados 30 dias antes da expiração, sem intervenção manual.
O fluxo automático usa o challenge HTTP-01: o Caddy coloca um ficheiro de verificação no servidor, a CA acede via HTTP (porto 80) e valida a propriedade do domínio. Isto funciona na maioria dos cenários, mas falha quando o servidor está atrás de um proxy que bloqueia o porto 80 ou quando o domínio aponta para um CDN.
Para esses casos, usa-se o DNS challenge (challenge DNS-01), que valida a propriedade do domínio criando um registo TXT em DNS. O Caddy suporta DNS challenge via plugins para fornecedores específicos:
exemplo.pt {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
root * /var/www/exemplo
file_server
}
O exemplo acima usa o plugin Cloudflare. A token de API deve estar numa variável de ambiente CF_API_TOKEN. Para usar DNS challenge, é preciso compilar o Caddy com o plugin correspondente (xcaddy ou binário customizado do site oficial).
Instalar via xcaddy com plugin DNS:
xcaddy build --with github.com/caddy-dns/cloudflare
sudo mv caddy /usr/bin/caddy
Para forçar uma CA específica (ex: apenas Let’s Encrypt):
exemplo.pt {
tls {
issuer acme {
dir https://acme-v02.api.letsencrypt.org/directory
}
}
root * /var/www/exemplo
file_server
}
Para ambientes de teste, usar a staging CA de Let’s Encrypt evita o rate limit da CA de produção:
exemplo.pt {
tls {
issuer acme {
dir https://acme-staging-v02.api.letsencrypt.org/directory
}
}
root * /var/www/exemplo
file_server
}
⚠ Rate limits ACME
Let’s Encrypt impõe limites: 50 certificados por domínio registado por semana, 5 falhas de validação por hora por conta. Em configuração inicial com muitos subdomínios, usar staging primeiro para evitar exaustão do limite.
Erros Comuns e Soluções
Os erros mais frequentes ao usar Caddy 2 em ambiente PME estão listados na tabela abaixo, com causa e solução.
| Erro | Causa | Solução |
|---|---|---|
| connection refused no porto 80 | Firewall bloqueia porto 80 (necessário para HTTP-01) | Abrir portos 80 e 443 no firewall |
| unable to authorize certificate | DNS ainda não propaga ou aponta para outro IP | Verificar com dig exemplo.pt e aguardar propagação |
| too many certificates (rate limit) | Excesso de pedidos à CA de produção | Usar staging CA para testes, aguardar janela de rate limit |
| Caddyfile syntax error | Indentação incorrecta ou chavetas em falta | Executar caddy validate --config Caddyfile |
| reverse_proxy 502 Bad Gateway | Backend não está a correr ou porto incorrecto | Verificar systemctl status app e porto no Caddyfile |
| certificado não renova | Porto 80 bloqueado ou DNS alterado | Verificar logs em /var/log/caddy/ e abertura do porto 80 |
| DNS challenge falha | Token de API incorrecta ou sem permissões | Verificar variável de ambiente e permissões da token no DNS |
Os logs do Caddy ficam em /var/log/caddy/ e são a primeira fonte de diagnóstico. Para ver logs em tempo real:
sudo journalctl -u caddy -f
O Caddy 2 oferece uma solução robusta para PME que precisam de servir sites com HTTPS sem a complexidade de gerir certificados manualmente. A combinação de configuração simples, HTTPS automático e suporte nativo para HTTP/3 reduz significativamente o tempo de administração do sistema.