Caddy : reverse proxy HTTPS automatique
Caddy fait du reverse proxy HTTPS sans aucune config manuelle de certificats. ACME, HTTP/2, HTTP/3, gzip, brotli, OCSP, automatique. Le serveur web "qui juste marche".
Introduction
Caddy est un serveur web moderne ecrit en Go avec une obsession : zero config pour HTTPS. Concretement :
- Obtient automatiquement des certificats Let's Encrypt / ZeroSSL
- Renouvelle automatiquement avant expiration
- HTTPS active par defaut
- HTTP/2 et HTTP/3 (QUIC) actives par defaut
- Reverse proxy simple a configurer
- Syntaxe Caddyfile ultra-lisible
- Hot-reload sans downtime
Idеal pour : sites perso, dev, prod simple, prototypage rapide. Pour les configs complexes, Nginx reste la reference.
Prerequis
- VPS Linux
- Ports 80 et 443 ouverts (necessaire pour ACME)
- Nom de domaine pointant vers le VPS
- Acces root
Etape 1 : Installation
Sur Debian / Ubuntu
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
Verifier
caddy version
sudo systemctl status caddy
Etape 2 : Le Caddyfile
Toute la config tient dans /etc/caddy/Caddyfile :
votre-domaine.fr {
respond "Hello, World!"
}
Reload :
sudo systemctl reload caddy
Visitez https://votre-domaine.fr : Caddy a obtenu un certificat Let's Encrypt automatiquement et sert "Hello, World!" en HTTPS.
⚠️ Aucune config SSL ! Caddy s'occupe de tout.
Etape 3 : Servir des fichiers statiques
votre-domaine.fr {
root * /var/www/html
file_server
}
Avec listing du dossier :
votre-domaine.fr {
root * /var/www/html
file_server browse
}
Etape 4 : Reverse proxy vers une app
Imaginons une app Node.js sur le port 3000 :
api.votre-domaine.fr {
reverse_proxy localhost:3000
}
Et c'est tout. HTTPS, HTTP/2, HTTP/3, redirection 80 -> 443. Tout est gere.
Multiple backends (load balancing) :
api.votre-domaine.fr {
reverse_proxy backend1:3000 backend2:3000 backend3:3000 {
lb_policy round_robin
health_uri /healthz
health_interval 10s
}
}
Etape 5 : Multi-sites
site1.fr {
root * /var/www/site1
file_server
}
site2.fr {
reverse_proxy localhost:8000
}
api.site2.fr {
reverse_proxy backend:3000
}
Chaque site a son propre certificat automatique.
Etape 6 : Configurations avancees
PHP avec PHP-FPM
votre-domaine.fr {
root * /var/www/html
php_fastcgi unix//run/php/php8.2-fpm.sock
file_server
}
Caddy gere le routing index.php automatiquement.
Compression
Activee par defaut (gzip + zstd). Pour ajouter brotli :
votre-domaine.fr {
encode gzip zstd
reverse_proxy localhost:3000
}
Headers de securite
votre-domaine.fr {
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
Permissions-Policy "geolocation=()"
}
reverse_proxy localhost:3000
}
Rate limiting
Caddy ne supporte pas le rate limiting nativement (sans plugin). Pour ca, utilisez le plugin officiel caddy-ratelimit :
sudo caddy add-package github.com/mholt/caddy-ratelimit
Puis :
votre-domaine.fr {
rate_limit {
zone main {
key {client_ip}
events 100
window 1m
}
}
reverse_proxy localhost:3000
}
Etape 7 : Wildcard certificate
Pour *.votre-domaine.fr, vous avez besoin de DNS-01 challenge. Caddy supporte de nombreux providers via plugins :
sudo caddy add-package github.com/caddy-dns/cloudflare
*.votre-domaine.fr {
tls {
dns cloudflare votre_token_cloudflare
}
@app1 host app1.votre-domaine.fr
handle @app1 {
reverse_proxy localhost:3001
}
@app2 host app2.votre-domaine.fr
handle @app2 {
reverse_proxy localhost:3002
}
}
Etape 8 : Logging
votre-domaine.fr {
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
}
format json
}
reverse_proxy localhost:3000
}
Parser :
sudo tail -f /var/log/caddy/access.log | jq
Etape 9 : Basic auth
admin.votre-domaine.fr {
basicauth /* {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfO...
}
reverse_proxy localhost:8080
}
Generer le hash :
caddy hash-password
Etape 10 : WebSockets
Aucune config supplementaire :
ws.votre-domaine.fr {
reverse_proxy localhost:3000
}
WebSockets transitent transparent.
Etape 11 : API admin
Caddy expose une API REST sur :2019 (localhost only par defaut) pour piloter dynamiquement :
# Voir la config courante
curl localhost:2019/config/ | jq
# Update une route sans reload
curl -X POST localhost:2019/config/apps/http/servers/srv0/routes \
-H "Content-Type: application/json" \
-d '{"match": [{"host": ["new.example.com"]}], "handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:9000"}]}]}'
Etape 12 : Migration depuis Nginx
Caddy lit la conf Nginx via :
caddy adapt --config /etc/nginx/sites-available/mon-site --adapter nginxconf
Vous obtenez un Caddyfile equivalent. Verifiez manuellement avant deploiement.
Depannage
Certificat ne se genere pas
Verifiez :
- Le port 80 est ouvert (HTTP-01)
- Le DNS du domaine pointe bien vers le VPS
- Pas d'autre service sur 80 (sinon Caddy ne peut pas faire HTTP-01)
Logs :
sudo journalctl -u caddy -f
502 Bad Gateway sur reverse_proxy
Le backend est down ou non joignable. Verifiez :
curl http://localhost:3000
"address already in use"
Un autre service utilise le 80/443 (Nginx, Apache). Stoppez-le ou utilisez d'autres ports.
Rate limit depasse par Let's Encrypt
Trop de tests. Passez en staging temporairement :
votre-domaine.fr {
tls {
ca https://acme-staging-v02.api.letsencrypt.org/directory
}
}
Commandes utiles
# Status
sudo systemctl status caddy
# Reload sans downtime
sudo systemctl reload caddy
# Tester le Caddyfile
caddy validate --config /etc/caddy/Caddyfile
# Format / normaliser le Caddyfile
caddy fmt /etc/caddy/Caddyfile --overwrite
# Logs
sudo journalctl -u caddy -f
# Lister les certs
ls /var/lib/caddy/.local/share/caddy/certificates/
# Forcer le renouvellement
sudo caddy reload --config /etc/caddy/Caddyfile
# Voir la config courante via API
curl localhost:2019/config/
Conclusion
Caddy est :
- Le serveur web "qui juste marche" (no SSL config needed)
- Adapte aux sites simples a moyens
- Tres rapide pour prototyper
- Plugins riches (DNS providers, rate limit, WAF, etc.)
Limites : pour des configs Nginx complexes (regex, locations imbriquees, OpenResty, scripting Lua), Nginx reste plus adapte.
Pour aller plus loin :
- Combinez avec Coraza WAF (plugin Caddy)
- Explorez les plugins : https://caddyserver.com/docs/modules/
- Utilisez Caddy en cluster avec stockage Redis partage
Ressources
- Documentation officielle : https://caddyserver.com/docs
- Caddyfile reference : https://caddyserver.com/docs/caddyfile
- Plugins : https://caddyserver.com/docs/modules/
- Source : https://github.com/caddyserver/caddy


















