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.
Caddy n'est pas un serveur HTTP avec quelques options. C'est un runtime de modules où le serveur HTTP est lui-même un module. Comprendre cette architecture change la façon dont on pense la configuration.
Tout ce que Caddy fait est décrit par un objet JSON. Le Caddyfile est un format humain qui se compile vers ce JSON. La structure de base :
{
"admin": {
"listen": "localhost:2019"
},
"logging": { ... },
"storage": { ... },
"apps": {
"http": { ... },
"tls": { ... },
"pki": { ... }
}
}Les apps sont les modules de haut niveau. Chaque app est indépendante — vous pouvez avoir Caddy sans serveur HTTP (juste PKI + TLS), ou avec plusieurs serveurs HTTP sur des ports différents.
{
"apps": {
"http": {
"http_port": 80,
"https_port": 443,
"servers": {
"main": {
"listen": [":443"],
"routes": [
{
"match": [{"host": ["example.com"]}],
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [{"dial": "localhost:3000"}]
}
]
}
]
}
}
}
}
}Une route = match + handle. L'évaluation suit l'ordre de déclaration — pas de score comme Nginx.
Matchers disponibles :
{
"match": [
{
"host": ["example.com", "*.example.com"],
"path": ["/api/*"],
"method": ["GET", "POST"],
"header": {"X-Custom": ["value*"]},
"header_regexp": {"Authorization": "Bearer (?P<token>.+)"},
"remote_ip": {"ranges": ["10.0.0.0/8"]},
"not": [{"path": ["/health"]}]
}
]
}Les conditions dans un même objet matcher sont ET. Plusieurs objets matcher dans le tableau sont OU.
Handler chain : les handlers s'exécutent en séquence dans l'ordre du tableau. Un handler peut décider de passer la requête au suivant ou de l'absorber.
{
"handle": [
{"handler": "authentication", "providers": {...}},
{"handler": "rate_limit", ...},
{"handler": "rewrite", "uri": "/internal{path}"},
{"handler": "reverse_proxy", "upstreams": [...]}
]
}Gère les certificats indépendamment de l'app HTTP. Elle peut obtenir des certificats pour des domaines qui ne sont pas encore routés.
{
"apps": {
"tls": {
"automation": {
"policies": [
{
"subjects": ["example.com", "*.example.com"],
"issuers": [
{
"module": "acme",
"ca": "https://acme-v02.api.letsencrypt.org/directory",
"challenges": {
"dns": {
"provider": {
"name": "cloudflare",
"api_token": "{env.CF_API_TOKEN}"
}
}
}
}
],
"key_type": "p256"
}
]
},
"certificates": {
"automate": ["example.com", "*.example.com"]
}
}
}
}Caddy peut être une autorité de certification interne. Elle émet des certificats pour vos services internes signés par une CA que vous contrôlez.
{
"apps": {
"pki": {
"certificate_authorities": {
"local": {
"name": "Caddy Local Authority",
"root": {
"format": "pem_file",
"certificate": "/etc/caddy/root.crt",
"private_key": "/etc/caddy/root.key"
}
}
}
}
}
}Ensuite dans la politique TLS :
{
"issuers": [
{
"module": "internal",
"ca": "local"
}
]
}Tous les certificats internes sont signés par votre CA. Distribuez le certificat root à vos clients une fois, et tous les services qui utilisent cette CA sont automatiquement reconnus.
Le Caddyfile est un DSL qui mappe vers la structure JSON. Comprendre la correspondance évite les surprises.
{
admin localhost:2019
email admin@example.com
key_type p256
}
example.com {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
reverse_proxy localhost:3000
}Compile vers (simplifié) :
{
"admin": {"listen": "localhost:2019"},
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [":443", ":80"],
"routes": [{
"match": [{"host": ["example.com"]}],
"handle": [{
"handler": "subroute",
"routes": [{
"handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:3000"}]}]
}]
}]
}]
}
}
},
"tls": {
"automation": {
"policies": [{
"subjects": ["example.com"],
"issuers": [{"module": "acme", "challenges": {"dns": {"provider": {"name": "cloudflare"}}}}]
}]
}
}
}
}Voir la compilation en live :
caddy adapt --config Caddyfile --adapter caddyfileIndispensable pour déboguer une configuration Caddyfile qui ne se comporte pas comme attendu — vous voyez exactement ce que Caddy exécute.
Chaque type de handler, matcher, logger, storage est un module avec un nom unique :
Handlers : file_server, reverse_proxy, static_response, rewrite,
redirect, authenticate, rate_limit, templates, encode
Matchers : host, path, method, header, remote_ip, expression, not
Storage : file_system, redis, s3
Loggers : console, json, filter
Issuers : acme, internal, zerossl
Challenges : http-01, tls-alpn-01, dns# Lister tous les modules disponibles dans votre build
caddy list-modules
# Modules HTTP spécifiquement
caddy list-modules --packages | grep httpL'architecture est claire. Le chapitre suivant couvre le Caddyfile avancé : snippets, matchers nommés, import, @, et les patterns de configuration réels.