Caddy e um servidor web moderno e de codigo aberto escrito em Go que se destaca por uma caracteristica principal: HTTPS automatico. Enquanto servidores web tradicionais como Nginx e Apache exigem configuracao manual de certificados com Certbot ou ferramentas similares, o Caddy obtem e renova certificados TLS do Let’s Encrypt no momento em que voce aponta um dominio para ele. Combinado com sua sintaxe de configuracao minima, proxy reverso integrado e suporte a HTTP/3, o Caddy se tornou a escolha preferida para desenvolvedores que desejam servico web seguro e pronto para producao com o minimo esforco possivel.
O que e o Caddy?
Caddy e uma plataforma de servidor web extensivel que prioriza a facilidade de uso e configuracoes seguras por padrao. Foi criado por Matt Holt em 2015 e e distribuido como um binario unico compilado estaticamente sem dependencias externas.
Caracteristicas principais do Caddy:
- HTTPS automatico — Provisiona e renova certificados TLS do Let’s Encrypt ou ZeroSSL sem nenhuma configuracao
- HTTP/2 e HTTP/3 — Habilitados por padrao para todos os sites HTTPS
- Proxy reverso — Proxy reverso integrado com balanceamento de carga, verificacoes de saude e manipulacao de cabecalhos
- Modo sem configuracao — Um Caddyfile simples de duas linhas pode servir um site completo com HTTPS
- Multiplataforma — Executa em Linux, macOS, Windows e BSD
- Ecossistema de plugins — Estenda funcionalidade com modulos para provedores DNS, autenticacao, limitacao de taxa e mais
O Caddy e distribuido sob a licenca Apache 2.0 e e gratuito tanto para uso pessoal quanto comercial.
Caddy vs Nginx
Se voce atualmente usa Nginx e esta se perguntando se o Caddy e adequado para seu projeto, aqui esta uma comparacao direta:
| Caracteristica | Caddy | Nginx |
|---|---|---|
| HTTPS | Automatico (cliente ACME integrado) | Manual (requer Certbot ou similar) |
| Sintaxe de configuracao | Caddyfile (minima, legivel) | nginx.conf (poderoso mas verboso) |
| HTTP/2 | Habilitado por padrao | Requer configuracao explicita |
| HTTP/3 (QUIC) | Integrado, habilitado por padrao | Experimental (requer build separado) |
| Proxy reverso | Diretiva integrada | Modulo integrado |
| Balanceamento de carga | Integrado com multiplas politicas | Integrado (round-robin, least_conn, etc.) |
| Recarregamento de config | Sem inatividade via API ou SIGHUP | Sem inatividade via nginx -s reload |
| Linguagem | Go (seguro em memoria) | C (alto desempenho) |
| Uso de memoria | Baixo (~20-50 MB) | Muito baixo (~5-15 MB) |
| Desempenho bruto | Muito bom | Excelente (lida com milhoes de RPS) |
| Comunidade e ecossistema | Crescendo rapidamente | Massivo, decadas de documentacao |
Quando escolher o Caddy: Voce quer HTTPS automatico, configuracao minima e um conjunto de recursos modernos sem gerenciamento manual de certificados. Ideal para aplicacoes auto-hospedadas, projetos pessoais e implantacoes pequenas a medias.
Quando escolher o Nginx: Voce precisa de controle extremamente granular, maximo desempenho bruto para milhoes de conexoes simultaneas, ou ampla compatibilidade de modulos de decadas de desenvolvimento do ecossistema.
Pre-requisitos
Antes de instalar o Caddy, certifique-se de ter:
- Um servidor Linux rodando Ubuntu 22.04+ ou Debian 12+ (outras distribuicoes tambem sao suportadas)
- Um nome de dominio com registros DNS A/AAAA apontando para o IP publico do seu servidor
- Portas 80 e 443 abertas no seu firewall (necessarias para o desafio ACME HTTP e HTTPS)
- Acesso root ou sudo ao servidor
- Nenhum outro servidor web (Nginx, Apache) ja escutando nas portas 80/443
Verifique se seu firewall permite as portas necessarias:
# Se usar UFW
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status
Instalando o Caddy no Ubuntu
O metodo de instalacao recomendado usa o repositorio APT oficial do Caddy, que fornece atualizacoes automaticas:
# Instalar dependencias necessarias
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
# Adicionar a chave GPG do Caddy
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
# Adicionar o repositorio do Caddy
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# Instalar o Caddy
sudo apt update
sudo apt install -y caddy
Verifique a instalacao:
caddy version
Voce devera ver uma saida como v2.8.4 h1:... confirmando que o Caddy esta instalado. A instalacao do pacote tambem cria um servico systemd, um Caddyfile padrao em /etc/caddy/Caddyfile, e um usuario caddy para executar o processo.
Alternativa: Instalar a partir do Binario
Se voce prefere uma instalacao manual ou precisa de uma versao especifica:
# Baixar a ultima versao
curl -Lo caddy.tar.gz "https://github.com/caddyserver/caddy/releases/latest/download/caddy_2.8.4_linux_amd64.tar.gz"
# Extrair e mover para o PATH
tar xzf caddy.tar.gz
sudo mv caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy
# Verificar
caddy version
Entendendo o Caddyfile
O Caddyfile e o arquivo de configuracao do Caddy. Sua sintaxe e intencionalmente minima — voce descreve o que quer, nao como alcancar. O Caddy preenche os padroes sensiveis.
O Caddyfile fica em /etc/caddy/Caddyfile quando instalado pelo gerenciador de pacotes. Aqui esta a estrutura basica:
# Opcoes globais (opcional)
{
email admin@example.com
}
# Bloco do site
example.com {
root * /var/www/html
file_server
}
Conceitos-chave:
- Endereco do site — O dominio ou IP antes da chave de abertura. Usar um nome de dominio ativa o HTTPS automatico.
- Diretivas — Comandos dentro do bloco do site como
root,file_server,reverse_proxy. - Opcoes globais — Configuracoes dentro de um bloco
{}de nivel superior sem endereco. Usadas para email (para registro ACME), padroes de logging, etc. - Matchers — Padroes como
*ou/api/*que controlam a quais requisicoes uma diretiva se aplica.
Apos editar o Caddyfile, valide e recarregue:
# Validar sintaxe
caddy validate --config /etc/caddy/Caddyfile
# Recarregar sem tempo de inatividade
sudo systemctl reload caddy
Servindo Arquivos Estaticos
Servir um site estatico com o Caddy requer apenas algumas linhas:
example.com {
root * /var/www/mysite
file_server
}
So isso. O Caddy vai:
- Obter um certificado TLS para
example.comautomaticamente - Servir arquivos de
/var/www/mysite - Habilitar HTTP/2 e HTTP/3
- Redirecionar HTTP para HTTPS
Para uma configuracao de site estatico mais completa com compressao e cache:
example.com {
root * /var/www/mysite
# Habilitar compressao gzip e zstd
encode gzip zstd
# Servir arquivos estaticos com navegacao de diretorio desabilitada
file_server {
hide .git .env
}
# Paginas de erro personalizadas
handle_errors {
rewrite * /{err.status_code}.html
file_server
}
# Cache para assets estaticos
@static path *.css *.js *.png *.jpg *.gif *.svg *.woff2
header @static Cache-Control "public, max-age=2592000, immutable"
# Cabecalhos de seguranca
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
}
Crie o diretorio raiz web e uma pagina de teste:
sudo mkdir -p /var/www/mysite
echo '<h1>Hello from Caddy</h1>' | sudo tee /var/www/mysite/index.html
sudo chown -R caddy:caddy /var/www/mysite
HTTPS Automatico
O HTTPS automatico e a caracteristica principal do Caddy. Entender como funciona ajuda voce a resolver problemas e personalizar o comportamento.
Como Funciona
Quando o Caddy encontra um bloco de site com um nome de dominio publico (nao localhost nem um IP), ele automaticamente:
- Verifica DNS — Confirma que o dominio resolve para o IP publico do servidor
- Solicita um certificado — Contata o Let’s Encrypt (ou ZeroSSL como fallback) via protocolo ACME
- Completa o desafio HTTP-01 — Prova propriedade do dominio servindo um token na porta 80
- Instala o certificado — Configura TLS com o certificado e chave obtidos
- Redireciona HTTP para HTTPS — Cria um redirecionamento automatico na porta 80
- Agenda a renovacao — Renova o certificado antes da expiracao (tipicamente 30 dias antes)
O Protocolo ACME
ACME (Automatic Certificate Management Environment) e o protocolo que o Let’s Encrypt usa para verificar a propriedade do dominio. O Caddy inclui um cliente ACME completo que suporta:
- Desafio HTTP-01 — Serve um arquivo de token via HTTP na porta 80 (padrao)
- Desafio TLS-ALPN-01 — Usa negociacao TLS na porta 443
- Desafio DNS-01 — Cria um registro TXT DNS (requer um plugin de provedor DNS)
Configurando o Email ACME
Defina um endereco de email para notificacoes de expiracao de certificados e registro de conta:
{
email admin@example.com
}
example.com {
reverse_proxy localhost:3000
}
Usando uma CA de Staging para Testes
Durante o desenvolvimento, use o ambiente staging do Let’s Encrypt para evitar limites de taxa:
{
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
example.com {
reverse_proxy localhost:3000
}
Importante: Certificados de staging nao sao confiaveis pelos navegadores. Remova a diretiva
acme_caao mover para producao.
Certificados Internos (Auto-assinados)
Para desenvolvimento local ou servicos internos que nao precisam de certificados publicos:
{
local_certs
}
localhost {
reverse_proxy localhost:3000
}
O Caddy gerara um certificado auto-assinado e instalara sua CA raiz no armazenamento de confianca do sistema para que os navegadores o aceitem localmente.
Configuracao do Proxy Reverso
A diretiva reverse_proxy do Caddy fornece um proxy reverso completo com configuracao minima.
Proxy Reverso Basico
app.example.com {
reverse_proxy localhost:3000
}
Esta unica linha redireciona todo o trafego de app.example.com para um backend rodando na porta 3000, com HTTPS automatico, HTTP/2 e encaminhamento adequado de cabecalhos.
Multiplos Backends em um Dominio
Use roteamento baseado em caminho para redirecionar diferentes paths para diferentes backends:
example.com {
reverse_proxy /api/* localhost:8000
reverse_proxy /admin/* localhost:9000
# Todo o resto serve arquivos estaticos
root * /var/www/frontend
file_server
}
Multiplos Dominios (Hosts Virtuais)
app.example.com {
reverse_proxy localhost:3000
}
api.example.com {
reverse_proxy localhost:8000
}
admin.example.com {
reverse_proxy localhost:9000 {
header_up X-Custom-Header "admin-panel"
}
}
Cada dominio obtem automaticamente seu proprio certificado TLS.
Preservando Informacoes do Cliente
O Caddy define automaticamente os cabecalhos X-Forwarded-For, X-Forwarded-Proto e X-Forwarded-Host. Voce pode adicionar ou sobrescrever cabecalhos:
app.example.com {
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Port {server_port}
}
}
Suporte a WebSocket
O Caddy redireciona conexoes WebSocket de forma transparente — nenhuma configuracao adicional e necessaria:
ws.example.com {
reverse_proxy localhost:4000
}
Os cabecalhos Upgrade e Connection sao tratados automaticamente pelo proxy reverso do Caddy.
Balanceamento de Carga
O Caddy suporta balanceamento de carga entre multiplas instancias backend com varias politicas.
Round-Robin (Padrao)
app.example.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003
}
Politicas de Balanceamento de Carga
app.example.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn
}
}
Politicas disponiveis:
| Politica | Descricao |
|---|---|
random | Escolhe um backend aleatorio |
least_conn | Envia para o backend com menos conexoes ativas |
round_robin | Cicla pelos backends sequencialmente (padrao) |
first | Sempre usa o primeiro backend disponivel |
ip_hash | Roteia baseado no IP do cliente para afinidade de sessao |
uri_hash | Roteia baseado no URI da requisicao |
header | Roteia baseado no valor de um cabecalho da requisicao |
cookie | Roteia baseado no valor de um cookie para persistencia de sessao |
Verificacoes de Saude
Habilite verificacoes de saude ativas para detectar e remover backends nao saudaveis:
app.example.com {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn
health_uri /health
health_interval 10s
health_timeout 5s
health_status 200
# Verificacoes de saude passivas
fail_duration 30s
max_fails 3
unhealthy_latency 500ms
}
}
Cabecalhos, Compressao e Cache
Cabecalhos de Resposta Personalizados
example.com {
header {
# Cabecalhos de seguranca
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
Permissions-Policy "camera=(), microphone=(), geolocation=()"
# Remover identificacao do servidor
-Server
# Controle de cache para conteudo dinamico
Cache-Control "no-store, no-cache, must-revalidate"
}
reverse_proxy localhost:3000
}
Compressao
Habilite compressao transparente com encode:
example.com {
encode zstd gzip
reverse_proxy localhost:3000
}
O Caddy negocia automaticamente o melhor algoritmo de compressao baseado no cabecalho Accept-Encoding do cliente. Zstandard (zstd) e preferido quando suportado, pois fornece melhores taxas de compressao e descompressao mais rapida que gzip.
Cache de Assets Estaticos
example.com {
@static path *.css *.js *.png *.jpg *.gif *.svg *.woff2 *.ico
header @static Cache-Control "public, max-age=31536000, immutable"
@dynamic not path *.css *.js *.png *.jpg *.gif *.svg *.woff2 *.ico
header @dynamic Cache-Control "no-cache, must-revalidate"
reverse_proxy localhost:3000
}
Executando o Caddy como Servico systemd
A instalacao do pacote APT cria um servico systemd automaticamente. Aqui estao os comandos essenciais:
# Iniciar o Caddy
sudo systemctl start caddy
# Parar o Caddy
sudo systemctl stop caddy
# Reiniciar o Caddy (breve inatividade)
sudo systemctl restart caddy
# Recarregar configuracao sem inatividade
sudo systemctl reload caddy
# Habilitar o Caddy para iniciar na inicializacao
sudo systemctl enable caddy
# Verificar status do servico
sudo systemctl status caddy
# Ver logs
sudo journalctl -u caddy --no-pager -f
O Arquivo de Servico do Caddy
O arquivo de unidade systemd padrao esta localizado em /lib/systemd/system/caddy.service. Ele executa o Caddy como o usuario caddy e carrega /etc/caddy/Caddyfile:
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
Nota: Se voce instalou o Caddy manualmente (nao do pacote), precisa criar este arquivo de servico voce mesmo e adicionar o usuario
caddycomsudo useradd --system --home /var/lib/caddy --shell /usr/sbin/nologin caddy.
Verificando a Instalacao
Apos iniciar o Caddy, verifique se ele esta servindo seu site:
# Verificar se o Caddy esta escutando
sudo ss -tlnp | grep caddy
# Testar HTTPS (substitua pelo seu dominio)
curl -I https://example.com
# Verificar detalhes do certificado
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -dates
Referencia de Diretivas do Caddyfile
Aqui esta uma referencia das diretivas do Caddyfile mais utilizadas:
| Diretiva | Proposito | Exemplo |
|---|---|---|
reverse_proxy | Redirecionar requisicoes para servidores backend | reverse_proxy localhost:3000 |
file_server | Servir arquivos estaticos do disco | file_server |
root | Definir o diretorio raiz do documento | root * /var/www/html |
encode | Habilitar compressao de respostas | encode gzip zstd |
header | Definir, adicionar ou remover cabecalhos de resposta | header X-Frame-Options "DENY" |
redir | Redirecionar requisicoes para uma nova URL | redir /old /new permanent |
rewrite | Reescrever o URI da requisicao internamente | rewrite /app/* /index.html |
basicauth | Proteger rotas com HTTP Basic Auth | basicauth /admin/* { ... } |
tls | Configurar ajustes TLS manualmente | tls internal |
log | Configurar registro de acesso | log { output file /var/log/caddy/access.log } |
handle | Agrupar diretivas para exclusividade mutua | handle /api/* { ... } |
handle_path | Como handle, mas remove o prefixo correspondente | handle_path /api/* { ... } |
respond | Retornar uma resposta estatica | respond "OK" 200 |
import | Incluir outro arquivo ou snippet | import /etc/caddy/snippets/* |
php_fastcgi | Redirecionar requisicoes PHP para PHP-FPM | php_fastcgi unix//run/php/php-fpm.sock |
Snippets Reutilizaveis
Defina blocos de configuracao reutilizaveis com snippets:
# Definir um snippet
(security_headers) {
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
}
# Usar o snippet em blocos de site
app.example.com {
import security_headers
reverse_proxy localhost:3000
}
api.example.com {
import security_headers
reverse_proxy localhost:8000
}
Solucao de Problemas
Problemas com Certificados
Se o Caddy nao conseguir obter um certificado, verifique estas causas comuns:
# Verificar resolucao DNS
dig +short example.com
# Garantir que as portas 80 e 443 sao acessiveis
sudo ss -tlnp | grep -E ':80|:443'
# Verificar se outro servico esta usando a porta 80
sudo lsof -i :80
# Ver logs do Caddy para erros ACME
sudo journalctl -u caddy --no-pager | grep -i "acme\|certificate\|tls"
Causas comuns de falhas em certificados:
- DNS nao aponta para seu servidor — O dominio deve resolver para o IP publico do servidor
- Porta 80 bloqueada pelo firewall — Necessaria para o desafio HTTP-01
- Outro servico usando a porta 80 — Pare o Nginx, Apache ou qualquer outro servidor web
- Limites de taxa — O Let’s Encrypt limita a emissao de certificados a 5 por dominio por semana
502 Bad Gateway
Isso significa que o Caddy nao consegue alcancar o backend upstream:
# Verificar se o backend esta rodando
curl -I http://localhost:3000
# Verificar se o backend esta vinculado a localhost ou a todas as interfaces
sudo ss -tlnp | grep 3000
# Solucao comum: garantir que o backend escuta em 127.0.0.1, nao em 0.0.0.0
Erros de Permissao
# Garantir que o usuario caddy tem acesso de leitura ao diretorio raiz web
sudo chown -R caddy:caddy /var/www/mysite
# Verificar permissoes de arquivos
ls -la /var/www/mysite/
# Se o Caddy nao conseguir vincular as portas 80/443
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/caddy
Validacao de Configuracao
# Sempre validar antes de recarregar
caddy validate --config /etc/caddy/Caddyfile
# Formatar o Caddyfile (corrigir indentacao)
caddy fmt --overwrite /etc/caddy/Caddyfile
# Testar com um adaptador especifico (ex., para configuracao JSON)
caddy adapt --config /etc/caddy/Caddyfile
API de Administracao do Caddy
O Caddy expoe uma API de administracao local em localhost:2019 para configuracao em tempo de execucao:
# Ver configuracao atual como JSON
curl http://localhost:2019/config/
# Verificar certificados carregados
curl http://localhost:2019/pki/ca/local
# Recarregar configuracao via API
curl -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
Resumo
O Caddy elimina a complexidade da configuracao do servidor web ao fornecer HTTPS automatico, uma sintaxe de Caddyfile minima e configuracoes padrao prontas para producao. Seja servindo arquivos estaticos, redirecionando para uma aplicacao backend com proxy reverso, ou balanceando carga entre multiplas instancias, o Caddy cuida do trabalho pesado — incluindo o gerenciamento de certificados TLS — para que voce possa se concentrar em construir sua aplicacao.
Para mais informacoes sobre configuracao de proxy reverso com Nginx, consulte nosso Guia Completo de Proxy Reverso com Nginx. Se voce precisa gerenciar certificados manualmente com Certbot para servidores que nao usam Caddy, confira Automatizar Certificados SSL com Let’s Encrypt e Certbot.