TL;DR — Resumo Rápido
Guia completo do Caddy como proxy reverso com HTTPS automático. Caddyfile, políticas de balanceamento, health checks e Caddyfile de produção para vários sites.
O Caddy é um servidor web moderno de código aberto escrito em Go cuja característica definidora é o HTTPS automático: ele provisiona e renova certificados TLS do Let’s Encrypt ou ZeroSSL no momento em que você aponta um domínio para ele, sem nenhuma configuração manual do Certbot. Como proxy reverso, o Caddy combina esse gerenciamento de TLS sem configuração com uma sintaxe declarativa limpa, balanceamento de carga integrado, HTTP/2 e HTTP/3 habilitados por padrão, e um único binário compilado estaticamente sem dependências externas. Este guia cobre tudo o que você precisa para executar o Caddy como proxy reverso em produção: instalação, sintaxe do Caddyfile, todas as políticas de balanceamento de carga, health checks ativos e passivos, manipulação de cabeçalhos, autenticação, TLS sob demanda, a API de administração e um Caddyfile completo para múltiplos sites.
Por Que Escolher o Caddy como Proxy Reverso
Aqui está uma comparação direta das principais opções de proxy reverso disponíveis em 2026:
| Recurso | Caddy | Nginx | Traefik | HAProxy | Apache |
|---|---|---|---|---|---|
| HTTPS automático | Cliente ACME integrado | Manual (Certbot) | Integrado (via ACME) | Manual | Manual (mod_md) |
| Formato de configuração | Caddyfile (mínimo) | nginx.conf (verboso) | YAML/TOML/rótulos Docker | haproxy.cfg | httpd.conf |
| HTTP/2 | Por padrão | Configuração explícita | Por padrão | Não (apenas TCP) | Configuração explícita |
| HTTP/3 (QUIC) | Por padrão | Experimental | Via plugin | Não | Não |
| Binário único | Sim (Go, sem deps) | Não (C, com módulos) | Sim (Go) | Sim (C) | Não |
| API de configuração | API REST completa | Não | API REST completa | Apenas socket de estatísticas | Não |
| Balanceamento de carga | 8 políticas integradas | Limitado integrado | Múltiplos provedores | Excelente | Básico |
| Uso de memória | ~20-50 MB | ~5-15 MB | ~25-60 MB | ~5-10 MB | ~30-80 MB |
| Curva de aprendizado | Baixa | Média-Alta | Média | Alta | Média-Alta |
Pré-requisitos
- Um servidor Linux com Ubuntu 22.04+, Debian 12+ ou uma distribuição compatível com RHEL/CentOS
- Um nome de domínio com registros DNS A/AAAA apontando para o IP público do servidor
- Portas 80 e 443 abertas no firewall
- Acesso root ou sudo
- Nenhum outro processo vinculado às portas 80 ou 443
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw status
Instalação do Caddy
Ubuntu e Debian (APT)
sudo apt update && 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 -y caddy
caddy version
RHEL, CentOS, Fedora (DNF)
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
Docker
docker run -d \
-p 80:80 -p 443:443 -p 443:443/udp \
-v /caminho/para/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
-v caddy_config:/config \
caddy:latest
xcaddy — Builds Personalizadas com Plugins
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-ratelimit
sudo mv caddy /usr/bin/caddy && sudo systemctl restart caddy
Sintaxe do Caddyfile
Estrutura
# Bloco de opções globais
{
email admin@exemplo.com
admin off
grace_period 10s
}
# Bloco de site — o domínio aciona HTTPS automático
app.exemplo.com {
diretiva argumento
}
Matchers
exemplo.com {
@api path /api/*
reverse_proxy @api localhost:8000
reverse_proxy /estatico/* localhost:9000
file_server *
}
Placeholders
exemplo.com {
reverse_proxy localhost:3000 {
header_up X-IP-Real {remote_host}
header_up X-Porta-Encam {server_port}
header_up X-ID-Requisicao {uuid}
}
}
Configuração do Proxy Reverso
Backend Único Básico
app.exemplo.com {
reverse_proxy localhost:3000
}
Roteamento Baseado em Caminho
exemplo.com {
reverse_proxy /api/* localhost:8000
reverse_proxy /ws/* localhost:4000
reverse_proxy /admin/* localhost:9000
root * /var/www/frontend
file_server
}
Manipulação de Cabeçalhos
app.exemplo.com {
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
header_up X-IP-Real {remote_host}
header_up X-Proto-Encam {scheme}
header_up -Authorization
header_down -X-ID-Servidor-Interno
header_down Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
}
}
WebSocket e Conexões de Longa Duração
ws.exemplo.com {
reverse_proxy localhost:4000 {
flush_interval -1
}
}
Balanceamento de Carga
Múltiplos Backends
app.exemplo.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003
}
Todas as Políticas de Balanceamento de Carga
app.exemplo.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn # Backend com menos conexões ativas
# lb_policy round_robin # Rotação sequencial (padrão)
# lb_policy first # Sempre o primeiro backend disponível
# lb_policy random # Seleção aleatória
# lb_policy ip_hash # IP do cliente → backend consistente
# lb_policy cookie caddy_lb # Persistência de sessão baseada em cookie
# lb_policy header X-Shard # Roteamento por valor de cabeçalho
# lb_policy uri_hash # URI da requisição → backend consistente
}
}
Health Checks Ativos
app.exemplo.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn
health_uri /health
health_interval 15s
health_timeout 5s
health_status 200
}
}
Health Checks Passivos
app.exemplo.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy round_robin
fail_duration 30s
max_fails 3
unhealthy_latency 500ms
unhealthy_status 5xx
}
}
HTTPS Automático em Profundidade
Tipos de Desafio ACME
{
email admin@exemplo.com
}
# HTTP-01 (padrão)
exemplo.com {
reverse_proxy localhost:3000
}
# TLS-ALPN-01: Usa porta 443
so-tls.exemplo.com {
tls {
challenges tls-alpn-01
}
reverse_proxy localhost:3001
}
# DNS-01: Sem portas de entrada — requer xcaddy + plugin DNS
wildcard.exemplo.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
reverse_proxy localhost:3002
}
TLS Sob Demanda para Domínios Dinâmicos
{
on_demand_tls {
ask http://localhost:9001/verificar-dominio
interval 2m
burst 5
}
}
:443 {
tls {
on_demand
}
reverse_proxy localhost:3000
}
CA Interna para Desenvolvimento
{
local_certs
}
localhost, 127.0.0.1, ::1 {
reverse_proxy localhost:3000
}
Autenticação
Autenticação Básica HTTP
admin.exemplo.com {
basicauth /admin/* {
alice $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GT.VVKf3KCrXxpHPkAXmn9sQHO
}
reverse_proxy localhost:9000
}
caddy hash-password --plaintext 'suasenha'
Autenticação Delegada (Authelia, oauth2-proxy)
app.exemplo.com {
forward_auth authelia:9091 {
uri /api/verify?rd=https://auth.exemplo.com
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy localhost:3000
}
Servidor de Arquivos e SPA
Servidor de Arquivos Estáticos
estatico.exemplo.com {
root * /var/www/html
encode gzip zstd
file_server {
hide .git .env .htaccess
}
}
Aplicação de Página Única (SPA)
spa.exemplo.com {
root * /var/www/app/dist
encode gzip zstd
try_files {path} /index.html
file_server
}
Compressão e Registro de Acesso
exemplo.com {
encode {
zstd
gzip 6
minimum_length 1024
}
log {
output file /var/log/caddy/acesso.log {
roll_size 100MiB
roll_keep 10
roll_keep_for 720h
}
format json
level INFO
}
reverse_proxy localhost:3000
}
A API de Administração do Caddy
# Ver configuração atual
curl http://localhost:2019/config/
# Recarregar configuração a partir do Caddyfile
curl -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
Caddyfile de Produção para Múltiplos Sites
{
email admin@exemplo.com
grace_period 30s
admin unix//run/caddy/admin.sock
}
(cabecalhos_seguranca) {
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
-X-Powered-By
}
}
app.exemplo.com {
import cabecalhos_seguranca
encode zstd gzip
log {
output file /var/log/caddy/app-acesso.log { roll_size 50MiB; roll_keep 7 }
format json
}
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn
health_uri /health
health_interval 10s
health_timeout 3s
fail_duration 30s
max_fails 3
header_up X-IP-Real {remote_host}
header_up X-Proto-Encam {scheme}
header_down -X-Rastreio-Interno
}
}
www.exemplo.com {
import cabecalhos_seguranca
root * /var/www/frontend/dist
encode zstd gzip
@estatico path *.css *.js *.png *.jpg *.webp *.gif *.svg *.woff2 *.ico
header @estatico Cache-Control "public, max-age=31536000, immutable"
try_files {path} /index.html
file_server
}
Armadilhas e Casos Especiais
A porta 80 deve ser acessível para desafios HTTP-01. Se seu provedor de nuvem bloquear a porta 80, use o desafio tls-alpn-01 ou DNS-01 com xcaddy e um plugin DNS.
Limites de taxa do Let’s Encrypt. O servidor ACME de produção permite 5 certificados duplicados por domínio por semana. Durante os testes, defina acme_ca https://acme-staging-v02.api.letsencrypt.org/directory.
O usuário caddy precisa de acesso de leitura às suas raízes web. Execute sudo chown -R caddy:caddy /var/www/seusite após criar ou copiar arquivos.
O intervalo de flush importa para streaming. Eventos enviados pelo servidor (SSE) e APIs de streaming requerem flush_interval -1 dentro do bloco reverse_proxy.
Solução de Problemas
# Validar sintaxe do Caddyfile
caddy validate --config /etc/caddy/Caddyfile
# Formatar automaticamente o Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile
# Ver registros em tempo real
sudo journalctl -u caddy -f --no-pager
# Verificar em quais portas o Caddy está ouvindo
sudo ss -tlnp | grep caddy
# Verificar certificado TLS
echo | openssl s_client -connect exemplo.com:443 -servername exemplo.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Resumo
- O Caddy é um único binário Go sem dependências externas que fornece HTTPS automático via ACME, HTTP/2 e HTTP/3 por padrão, e uma sintaxe Caddyfile mínima
- A diretiva
reverse_proxylida com proxying, balanceamento de carga, manipulação de cabeçalhos, suporte WebSocket e health checks em um único bloco - Oito políticas de balanceamento de carga cobrem todos os cenários, desde round-robin sem estado até afinidade de sessão baseada em cookies
- Health checks ativos e passivos podem ser combinados para detecção robusta de falhas
- O TLS sob demanda permite emissão de certificados por tenant para plataformas SaaS sem pré-configuração
- Use snippets para compartilhar blocos de configuração entre múltiplas definições de sites