Como instalar o servidor web Caddy com HTTPS automático
Instalar o Caddy no Ubuntu a partir do repositório oficial, escrever um Caddyfile para sites estáticos e proxies reversos, entender certificados automáticos, systemd, logs e erros comuns ao migrar do Nginx.

O Caddy é um servidor web que obtém e renova certificados TLS por padrão. Num VPS pequeno que hospeda um ou dois domínios, isso elimina uma classe inteira de timers Certbot e arquivos de snippet Nginx. A linguagem de configuração (Caddyfile) é curta. Proxy reverso, gzip e HTTP/2 são recursos normais, não um fim de semana de módulos extras.
O Nginx continua sendo a escolha certa para alguns times: vocês já têm configs de batalha, ou precisam de um módulo bem específico. Este guia é para o outro caso comum — você quer HTTPS que funcione num VPS Hiddence novo sem decorar snippets include. Vamos instalar o Caddy a partir do repositório apt oficial, explicar como ele fala com o Let's Encrypt, servir um site estático, fazer proxy de um app local, hospedar vários domínios, olhar os logs e cobrir as brigas usuais pela porta 80 com Apache ou um Nginx velho.
Quando o Caddy encaixa bem
O HTTPS automático é o título, mas o ganho do dia a dia são menos peças móveis. O Caddy escuta nas 80 e 443, redireciona HTTP para HTTPS e guarda certificados no próprio diretório de dados. Você ainda precisa de um domínio apontando para o VPS. Você ainda não pode quebrar o ACME (firewall 80/tcp, nenhum outro processo roubando :80). Certificados wildcard precisam de um módulo de provedor DNS — isso é um caminho mais longo do que um certificado de um único host.
- Redirecionamento HTTP→HTTPS automático e renovação de certificados
- Caddyfile legível em vez de blocos server longos
- Proxy reverso capaz para Node, Python, PHP-FPM com config extra, ou backends Docker
- HTTP/2 e padrões TLS modernos sem uma planilha de cifras
- Unidade systemd do pacote oficial
Requisitos
Um domínio precisa resolver para este VPS antes de o Caddy conseguir provar ACME HTTP-01. Se o DNS ainda estiver propagando, o Caddy vai falhar a emissão e tentar de novo; parece «o Caddy quebrou» quando é só DNS. Pare o Apache ou o Nginx primeiro se eles forem donos de 80/443.
- Ubuntu 22.04 ou 24.04
- Um registro A do domínio para o IP do VPS (e AAAA se você usa IPv6)
- Portas 80 e 443 livres e liberadas no firewall
- Root ou sudo
Passo 1: Instalar o Caddy a partir do repositório oficial
Não instale um Caddy velho aleatório do universo Ubuntu se você quer comportamento TLS e ACME atuais. O projeto Caddy documenta uma origem apt. Depois da instalação, o usuário caddy existe e o serviço fica habilitado.
ssh root@YOUR_VPS_IP
apt update && apt -y install debian-keyring debian-archive-keyring apt-transport-https curl gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update
apt -y install caddy
caddy version
systemctl status caddy --no-pagerPasso 2: Primeiro Caddyfile — site estático
O Caddyfile padrão é /etc/caddy/Caddyfile. Substitua pelo seu domínio. O Caddy tenta obter um certificado assim que a config carrega se o hostname não for localhost. Coloque os arquivos do site num diretório legível pelo usuário caddy (muitas vezes permissões no estilo www-data, mas o pacote usa o usuário caddy).
mkdir -p /var/www/example
echo '<h1>It works</h1>' > /var/www/example/index.html
chown -R caddy:caddy /var/www/example
cat >/etc/caddy/Caddyfile <<'EOF'
example.com {
root * /var/www/example
file_server
encode gzip
}
EOF
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
# Watch issuance:
journalctl -u caddy -fPasso 3: Proxy reverso de um aplicativo local
Se Gunicorn, Node ou Docker escutam em 127.0.0.1:8000, o Caddy deve ser o único processo público. A diretiva reverse_proxy encaminha Host e os cabeçalhos X-Forwarded-* de um jeito razoável para a maioria dos apps. Se o app gera URLs HTTP absolutos, configure as flags de proxy confiável / HTTPS no app (Django SECURE_PROXY_SSL_HEADER, Express trust proxy e assim por diante).
app.example.com {
encode gzip
reverse_proxy 127.0.0.1:8000
}
# Several hosts in one file are normal:
# blog.example.com {
# root * /var/www/blog
# file_server
# }Passo 4: Firewall e systemd
Libere 80 e 443. A unidade do Caddy é caddy.service; um reload basta depois de editar o Caddyfile se o processo estiver saudável. Se você mudar variáveis de ambiente de um plugin DNS, um restart completo fica mais claro. Os certificados moram por padrão em /var/lib/caddy/.local/share/caddy/ — inclua esse caminho nos backups se limites de taxa numa reinstalação importam para você.
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
systemctl enable --now caddy
systemctl reload caddy
# Backup cert storage (path may vary slightly by version):
ls -la /var/lib/caddy/Passo 5: Logs, compressão e cabeçalhos
Logs de acesso ajudam quando um bot martela um caminho ou quando você depura 404. Dá para logar por site. Acrescente cabeçalhos de segurança se você hospeda um app de navegador; não copie um pacote enorme de cabeçalhos sem entender HSTS (depois que você define um max-age longo, os navegadores lembram).
example.com {
root * /var/www/example
file_server
encode gzip
log {
output file /var/log/caddy/example.log
}
header {
X-Content-Type-Options nosniff
Referrer-Policy no-referrer-when-downgrade
-Server
}
}
mkdir -p /var/log/caddy
chown caddy:caddy /var/log/caddy
systemctl reload caddyPasso 6: PHP e outros extras
O Caddy fala com o PHP-FPM pela diretiva php_fastcgi. Isso basta para muitos hostings WordPress ou Laravel, mas você ainda precisa do php-fpm instalado e de um caminho de socket que bata. Se você já tem um config PHP Nginx perfeito, migrar numa noite é opcional — o Caddy brilha mais em proxy reverso + estático + TLS automático.
example.com {
root * /var/www/example
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
}
# Confirm FPM is running:
systemctl status php8.3-fpmMigrar do Nginx sem surpresas de downtime
Pare o Nginx antes de subir o Caddy ou eles vão brigar por 80/443. Baixe o TTL de DNS no dia anterior se você também estiver mudando de IP. Teste com curl --resolve para bater no VPS novo antes de trocar o registro A. Mantenha os configs Nginx no git por uma semana caso precise voltar atrás.
- systemctl stop nginx && systemctl disable nginx
- Instale o Caddy, valide o Caddyfile, suba o Caddy
- curl -I --resolve example.com:443:NEW_IP https://example.com
- Só então mude o DNS se o IP for novo
- A reemissão é automática; não rode também o Certbot contra o mesmo hostname
Solução de problemas
Falhas ACME quase sempre são DNS, firewall ou outro serviço na porta 80. As linhas de log do Caddy mencionam tls.obtain. Se o site funciona em HTTP mas não em HTTPS, a emissão nunca concluiu. Se você vê certificados demais, bateu nos limites de taxa do Let's Encrypt — use a CA de staging nos testes, não a de produção.
- validate falha: sintaxe do Caddyfile, chave faltando
- permission denied em root: chown caddy para o diretório do site
- bind: address already in use — ss -tulpn | grep -E ':80|:443'
- timeout do certificado: dig +short do domínio a partir do VPS, ufw allow 80
- 502 reverse_proxy: backend fora, ou você fez proxy para localhost a partir de uma rede de containers de forma errada
Notas de segurança
Os padrões TLS do Caddy são conservadores. O seu trabalho é segurança do aplicativo e SSH. Não habilite a API de administração do Caddy numa interface pública. O endpoint de admin padrão é local; deixe assim. Se você usar um Caddyfile da internet, leia cada matcher — um snippet que faz reverse_proxy de /* para um IP interno pode virar um proxy aberto.
- Não exponha a API de administração
- Mantenha o pacote atualizado
- HSTS só depois de ter certeza de que o HTTPS funciona para todos os hostnames
- Separe hostnames de teste e de produção para proteger os limites de taxa ACME
Dicas
- caddy fmt --overwrite /etc/caddy/Caddyfile mantém o arquivo legível
- Use snippets import quando tiver muitos sites parecidos
- No Docker, a imagem caddy:alpine com um Caddyfile montado é comum
- Certificados wildcard precisam de um módulo DNS e um token de API — proteja esse token
- Leia journalctl -u caddy antes de reescrever o arquivo inteiro
Caddy num VPS é: pacote oficial, um Caddyfile curto, portas 80/443 abertas, DNS já apontando para o servidor e reload systemd depois das edições. Use como servidor de arquivos estáticos ou como proxy reverso na frente de Gunicorn, Node ou Docker. O HTTPS automático funciona quando o ACME consegue responder na porta 80; se a emissão falhar, corrija DNS e conflitos de porta antes de culpar o Caddy. Faça backup de /var/lib/caddy se você reinstala com frequência.