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:

RecursoCaddyNginxTraefikHAProxyApache
HTTPS automáticoCliente ACME integradoManual (Certbot)Integrado (via ACME)ManualManual (mod_md)
Formato de configuraçãoCaddyfile (mínimo)nginx.conf (verboso)YAML/TOML/rótulos Dockerhaproxy.cfghttpd.conf
HTTP/2Por padrãoConfiguração explícitaPor padrãoNão (apenas TCP)Configuração explícita
HTTP/3 (QUIC)Por padrãoExperimentalVia pluginNãoNão
Binário únicoSim (Go, sem deps)Não (C, com módulos)Sim (Go)Sim (C)Não
API de configuraçãoAPI REST completaNãoAPI REST completaApenas socket de estatísticasNão
Balanceamento de carga8 políticas integradasLimitado integradoMúltiplos provedoresExcelenteBásico
Uso de memória~20-50 MB~5-15 MB~25-60 MB~5-10 MB~30-80 MB
Curva de aprendizadoBaixaMédia-AltaMédiaAltaMé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_proxy lida 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

Artigos Relacionados