Caddy de A à Z pour experts : Admin API REST, HTTPS automatique (ACME, DNS challenge, PKI interne), reverse proxy avancé, modules, on-demand TLS, clustering et production.
L'écosystème de modules Caddy couvre l'authentification, le rate limiting, la sécurité, le DNS, le stockage. Ce chapitre couvre les modules les plus utiles en production et comment en écrire un from scratch.
# Installer xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# Build avec modules
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-ratelimit \
--with github.com/greenpau/caddy-security \
--with github.com/caddyserver/cache-handler \
--with github.com/dunglas/caddy-cbrotli
# Build avec version spécifique de Caddy
xcaddy build v2.9.1 \
--with github.com/caddy-dns/cloudflare@latest
# Remplacer le binaire système
sudo mv ./caddy /usr/bin/caddy
sudo systemctl restart caddyforward_auth envoie chaque requête à un service d'authentification externe avant de la transmettre à l'upstream. Si le service répond 2xx, la requête passe. Sinon, l'utilisateur reçoit l'erreur (401, 302 vers login, etc.).
example.com {
forward_auth authelia:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy backend:3000 {
header_up X-User {header.Remote-User}
header_up X-Groups {header.Remote-Groups}
}
}Avec Authentik (alternative à Authelia) :
example.com {
forward_auth authentik:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-authentik-username X-authentik-groups X-authentik-email
}
reverse_proxy backend:3000
}Module de rate limiting qui s'intègre proprement dans la chaîne de handlers :
xcaddy build --with github.com/mholt/caddy-ratelimitapi.example.com {
rate_limit {
distributed # partage l'état en cluster
storage redis {
address localhost:6379
}
zone api_global {
key {remote_host} # par IP
events 1000
window 1m
}
zone api_endpoint {
key {remote_host}|{path} # par IP + endpoint
events 60
window 1m
}
}
@authenticated header Authorization "Bearer *"
handle @authenticated {
rate_limit {
zone authenticated_users {
key {header.Authorization}
events 10000
window 1m
}
}
reverse_proxy backend:3000
}
handle {
rate_limit {
zone anonymous {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy backend:3000
}
}caddy-security est un module qui implémente OAuth2, SAML, LDAP, MFA, et plus directement dans Caddy, sans service externe.
xcaddy build --with github.com/greenpau/caddy-security{
order authenticate before respond
order authorize before reverse_proxy
security {
local identity store localdb {
realm local
path /etc/caddy/users.json
}
authentication portal myportal {
crypto default token lifetime 3600
crypto key sign-verify {env.JWT_SECRET}
enable identity store localdb
cookie domain example.com
cookie insecure off
ui {
links {
"My App" /app icon "las la-rocket"
}
}
}
authorization policy mypolicy {
set auth url https://auth.example.com/
allow roles authp/admin authp/user
crypto key verify {env.JWT_SECRET}
acl rule {
comment allow users
match role authp/user
allow stop log info
}
}
}
}
auth.example.com {
authenticate with myportal
}
app.example.com {
authorize with mypolicy
reverse_proxy backend:3000
}xcaddy build --with github.com/caddyserver/cache-handlerapi.example.com {
cache {
api {
basepath /cache
}
regex {
exclude .*
}
key {
disable_body
disable_host
disable_method
disable_query
headers X-API-Version
}
ttl 5m
default_cache_control "public, max-age=300"
}
reverse_proxy backend:3000
}Caddy inclut gzip/zstd natifs. Pour Brotli :
xcaddy build --with github.com/dunglas/caddy-cbrotliexample.com {
encode zstd br gzip {
minimum_length 1024
}
reverse_proxy backend:3000
}Un module Caddy est un package Go qui implémente une interface. Voici un handler qui ajoute un header de corrélation à chaque requête.
├── go.mod
├── go.sum
└── correlationid/
└── correlationid.gopackage correlationid
import (
"crypto/rand"
"encoding/hex"
"net/http"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
func init() {
caddy.RegisterModule(CorrelationID{})
}
// CorrelationID ajoute un X-Correlation-ID header à chaque requête
type CorrelationID struct {
HeaderName string `json:"header_name,omitempty"`
}
func (CorrelationID) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.correlation_id",
New: func() caddy.Module { return new(CorrelationID) },
}
}
func (c *CorrelationID) Provision(ctx caddy.Context) error {
if c.HeaderName == "" {
c.HeaderName = "X-Correlation-ID"
}
return nil
}
func (c CorrelationID) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
id := r.Header.Get(c.HeaderName)
if id == "" {
b := make([]byte, 16)
rand.Read(b)
id = hex.EncodeToString(b)
r.Header.Set(c.HeaderName, id)
}
w.Header().Set(c.HeaderName, id)
return next.ServeHTTP(w, r)
}
var (
_ caddy.Provisioner = (*CorrelationID)(nil)
_ caddyhttp.MiddlewareHandler = (*CorrelationID)(nil)
)# Depuis le répertoire du module
xcaddy build \
--with github.com/yourorg/caddy-correlationid=./
# Ou héberger sur GitHub puis
xcaddy build \
--with github.com/yourorg/caddy-correlationid@v1.0.0{
"handler": "correlation_id",
"header_name": "X-Request-ID"
}example.com {
correlation_id {
header_name X-Request-ID
}
reverse_proxy backend:3000
}// Interfaces disponibles selon les besoins du module
type MyModule struct{}
// Obligatoire — identification du module
func (MyModule) CaddyModule() caddy.ModuleInfo
// Configuration et validation
func (*MyModule) Provision(ctx caddy.Context) error
func (*MyModule) Validate() error
func (*MyModule) Cleanup() error
// Selon le type de module
func (*MyModule) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error // handler
func (*MyModule) Match(r *http.Request) bool // matcher
// Sérialisation
type MyModule struct {
Option string `json:"option,omitempty"`
}cloudflare github.com/caddy-dns/cloudflare
route53 github.com/caddy-dns/route53
digitalocean github.com/caddy-dns/digitalocean
gcloud github.com/caddy-dns/googlecloud
azure github.com/caddy-dns/azure
namecheap github.com/caddy-dns/namecheap
ovh github.com/caddy-dns/ovh
hetzner github.com/caddy-dns/hetzner
bunny github.com/caddy-dns/bunnyfile_system Intégré — stockage local (défaut)
redis github.com/pberkel/caddy-storage-redis
s3 github.com/sagikazarmark/caddy-fs-s3
consul github.com/pteich/caddy-tlsconsulConfiguration du storage Redis (pour les clusters) :
{
"storage": {
"module": "redis",
"host": "redis:6379",
"password": "{env.REDIS_PASSWORD}",
"db": 0,
"key_prefix": "caddy:"
}
}Les modules sont maîtrisés. Dernier chapitre : production — logs structurés, métriques Prometheus, clustering, Docker et Kubernetes.