TL;DR — Résumé Rapide
Guide complet de Caddy comme proxy inverse avec HTTPS automatique. Caddyfile, politiques d'équilibrage, health checks et Caddyfile de production multi-sites.
Caddy est un serveur web moderne open source écrit en Go dont la caractéristique principale est le HTTPS automatique : il provisionne et renouvelle les certificats TLS depuis Let’s Encrypt ou ZeroSSL dès que vous pointez un domaine vers lui, sans aucune configuration manuelle de Certbot. En tant que proxy inverse, Caddy combine cette gestion TLS sans configuration avec une syntaxe déclarative épurée, un équilibrage de charge intégré, HTTP/2 et HTTP/3 activés par défaut, et un unique binaire compilé statiquement sans dépendances externes. Ce guide couvre tout ce dont vous avez besoin pour exécuter Caddy comme proxy inverse en production : installation, syntaxe du Caddyfile, toutes les politiques d’équilibrage de charge, health checks actifs et passifs, manipulation d’en-têtes, authentification, TLS à la demande, l’API d’administration et un Caddyfile complet pour l’hébergement multi-sites.
Pourquoi Choisir Caddy comme Proxy Inverse
Voici une comparaison directe des principales options de proxy inverse disponibles en 2026 :
| Fonctionnalité | Caddy | Nginx | Traefik | HAProxy | Apache |
|---|---|---|---|---|---|
| HTTPS automatique | Client ACME intégré | Manuel (Certbot) | Intégré (via ACME) | Manuel | Manuel (mod_md) |
| Format de configuration | Caddyfile (minimal) | nginx.conf (verbeux) | YAML/TOML/étiquettes Docker | haproxy.cfg | httpd.conf |
| HTTP/2 | Par défaut | Configuration explicite | Par défaut | Non (TCP uniquement) | Configuration explicite |
| HTTP/3 (QUIC) | Par défaut | Expérimental | Via plugin | Non | Non |
| Binaire unique | Oui (Go, sans deps) | Non (C, avec modules) | Oui (Go) | Oui (C) | Non |
| API de configuration | API REST complète | Non | API REST complète | Socket de statistiques uniquement | Non |
| Équilibrage de charge | 8 politiques intégrées | Limité intégré | Multiples fournisseurs | Excellent | Basique |
| Empreinte mémoire | ~20-50 Mo | ~5-15 Mo | ~25-60 Mo | ~5-10 Mo | ~30-80 Mo |
| Courbe d’apprentissage | Faible | Moyenne-Élevée | Moyenne | Élevée | Moyenne-Élevée |
Prérequis
- Un serveur Linux avec Ubuntu 22.04+, Debian 12+ ou une distribution compatible RHEL/CentOS
- Un nom de domaine avec des enregistrements DNS A/AAAA pointant vers l’IP publique du serveur
- Les ports 80 et 443 ouverts dans votre pare-feu
- Accès root ou sudo
- Aucun autre processus lié aux ports 80 ou 443
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw status
Installation de Caddy
Ubuntu et 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 /chemin/vers/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
-v caddy_config:/config \
caddy:latest
xcaddy — Builds Personnalisées avec 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
Syntaxe du Caddyfile
Structure
# Bloc d'options globales
{
email admin@exemple.fr
admin off
grace_period 10s
}
# Bloc de site — le domaine déclenche le HTTPS automatique
app.exemple.fr {
directive argument
}
Matchers
exemple.fr {
@api path /api/*
reverse_proxy @api localhost:8000
reverse_proxy /statique/* localhost:9000
file_server *
}
Espaces réservés (Placeholders)
exemple.fr {
reverse_proxy localhost:3000 {
header_up X-IP-Reel {remote_host}
header_up X-Port-Trans {server_port}
header_up X-ID-Requete {uuid}
}
}
Configuration du Proxy Inverse
Backend Unique de Base
app.exemple.fr {
reverse_proxy localhost:3000
}
Cette ligne unique fournit : HTTPS automatique, HTTP/2, HTTP/3, redirection HTTP→HTTPS, transfert des en-têtes X-Forwarded-For et support transparent des WebSocket.
Routage par Chemin
exemple.fr {
reverse_proxy /api/* localhost:8000
reverse_proxy /ws/* localhost:4000
reverse_proxy /admin/* localhost:9000
root * /var/www/frontend
file_server
}
Manipulation des En-têtes
app.exemple.fr {
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
header_up X-IP-Reel {remote_host}
header_up X-Proto-Trans {scheme}
header_up -Authorization
header_down -X-ID-Serveur-Interne
header_down Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
}
}
WebSocket et Connexions Longue Durée
ws.exemple.fr {
reverse_proxy localhost:4000 {
flush_interval -1
}
}
Équilibrage de Charge
Plusieurs Backends
app.exemple.fr {
reverse_proxy localhost:3001 localhost:3002 localhost:3003
}
Toutes les Politiques d’Équilibrage de Charge
app.exemple.fr {
reverse_proxy localhost:3001 localhost:3002 localhost:3003 {
lb_policy least_conn # Backend avec le moins de connexions actives
# lb_policy round_robin # Rotation séquentielle (par défaut)
# lb_policy first # Toujours le premier backend disponible
# lb_policy random # Sélection aléatoire
# lb_policy ip_hash # IP client → backend cohérent
# lb_policy cookie caddy_lb # Persistance de session par cookie
# lb_policy header X-Shard # Routage par valeur d'en-tête
# lb_policy uri_hash # URI de la requête → backend cohérent
}
}
Health Checks Actifs
app.exemple.fr {
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 Passifs
app.exemple.fr {
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 Automatique en Détail
Types de Défis ACME
{
email admin@exemple.fr
}
# HTTP-01 (par défaut)
exemple.fr {
reverse_proxy localhost:3000
}
# TLS-ALPN-01 : utilise le port 443
tls-seulement.exemple.fr {
tls {
challenges tls-alpn-01
}
reverse_proxy localhost:3001
}
# DNS-01 : sans ports entrants — nécessite xcaddy + plugin DNS
wildcard.exemple.fr {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
reverse_proxy localhost:3002
}
TLS à la Demande pour les Domaines Dynamiques
{
on_demand_tls {
ask http://localhost:9001/verifier-domaine
interval 2m
burst 5
}
}
:443 {
tls {
on_demand
}
reverse_proxy localhost:3000
}
CA Interne pour le Développement
{
local_certs
}
localhost, 127.0.0.1, ::1 {
reverse_proxy localhost:3000
}
Authentification
Authentification Basique HTTP
admin.exemple.fr {
basicauth /admin/* {
alice $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GT.VVKf3KCrXxpHPkAXmn9sQHO
}
reverse_proxy localhost:9000
}
caddy hash-password --plaintext 'votremotdepasse'
Authentification Déléguée (Authelia, oauth2-proxy)
app.exemple.fr {
forward_auth authelia:9091 {
uri /api/verify?rd=https://auth.exemple.fr
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy localhost:3000
}
Serveur de Fichiers et SPA
Serveur de Fichiers Statiques
statique.exemple.fr {
root * /var/www/html
encode gzip zstd
file_server {
hide .git .env .htaccess
}
}
Application à Page Unique (SPA)
spa.exemple.fr {
root * /var/www/app/dist
encode gzip zstd
try_files {path} /index.html
file_server
}
Compression et Journalisation des Accès
exemple.fr {
encode {
zstd
gzip 6
minimum_length 1024
}
log {
output file /var/log/caddy/acces.log {
roll_size 100MiB
roll_keep 10
roll_keep_for 720h
}
format json
level INFO
}
reverse_proxy localhost:3000
}
L’API d’Administration de Caddy
# Voir la configuration actuelle
curl http://localhost:2019/config/
# Recharger la configuration depuis le Caddyfile
curl -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
Caddyfile de Production pour Sites Multiples
{
email admin@exemple.fr
grace_period 30s
admin unix//run/caddy/admin.sock
}
(en_tetes_securite) {
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.exemple.fr {
import en_tetes_securite
encode zstd gzip
log {
output file /var/log/caddy/app-acces.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-Reel {remote_host}
header_up X-Proto-Trans {scheme}
header_down -X-Trace-Interne
}
}
www.exemple.fr {
import en_tetes_securite
root * /var/www/frontend/dist
encode zstd gzip
@statique path *.css *.js *.png *.jpg *.webp *.gif *.svg *.woff2 *.ico
header @statique Cache-Control "public, max-age=31536000, immutable"
try_files {path} /index.html
file_server
}
Pièges et Cas Particuliers
Le port 80 doit être accessible pour les défis HTTP-01. Si votre fournisseur cloud bloque le port 80, utilisez le défi tls-alpn-01 ou DNS-01 via xcaddy avec un plugin DNS.
Limites de débit de Let’s Encrypt. Le serveur ACME de production autorise 5 certificats dupliqués par domaine par semaine. Pendant les tests, définissez acme_ca https://acme-staging-v02.api.letsencrypt.org/directory.
L’utilisateur caddy a besoin d’un accès en lecture à vos racines web. Le service systemd s’exécute en tant qu’utilisateur système caddy. Exécutez toujours sudo chown -R caddy:caddy /var/www/votresite.
L’intervalle de vidage est important pour le streaming. Les Server-Sent Events (SSE) et les API de streaming nécessitent flush_interval -1 dans le bloc reverse_proxy.
Dépannage
# Valider la syntaxe du Caddyfile
caddy validate --config /etc/caddy/Caddyfile
# Formater automatiquement le Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile
# Surveiller les journaux en direct
sudo journalctl -u caddy -f --no-pager
# Vérifier les ports d'écoute de Caddy
sudo ss -tlnp | grep caddy
# Vérifier le certificat TLS
echo | openssl s_client -connect exemple.fr:443 -servername exemple.fr 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Résumé
- Caddy est un unique binaire Go sans dépendances externes qui fournit HTTPS automatique via ACME, HTTP/2 et HTTP/3 par défaut, et une syntaxe Caddyfile minimale
- La directive
reverse_proxygère le proxying, l’équilibrage de charge, la manipulation d’en-têtes, le support WebSocket et les health checks dans un seul bloc - Huit politiques d’équilibrage de charge couvrent tous les scénarios, du round-robin sans état à l’affinité de session par cookie
- Les health checks actifs et passifs peuvent être combinés pour une détection robuste des pannes
- Le TLS à la demande permet l’émission de certificats par tenant pour les plateformes SaaS sans pré-configuration
- Utilisez des snippets pour partager des blocs de configuration entre plusieurs définitions de sites