TLS sans douleur : ce que Caddy fait à ta place
Certbot t'oblige à comprendre les hooks de renouvellement, les timers systemd et les permissions sur /etc/letsencrypt. Caddy demande trois lignes. Voici ce qui se passe réellement derrière, pour ne pas déléguer aveuglément.
Je vois passer beaucoup de configurations Nginx + Certbot en audit, et une proportion inquiétante a un certificat expiré parce que le timer de renouvellement a échoué en silence six semaines plus tôt. Caddy supprime cette classe entière de problèmes — mais déléguer sans comprendre reste une dette. Alors regardons sous le capot.
La configuration, d’abord
cdeper.net {
encode zstd gzip
root * /srv/site
file_server
}
C’est tout. Au premier démarrage, Caddy obtient un certificat Let’s Encrypt, sert le site en HTTPS, redirige le port 80 vers 443, et programmera le renouvellement. Aucun timer à écrire, aucun hook à débugger.
Ce qui se passe réellement au premier lancement
- Caddy voit un nom de domaine dans le Caddyfile et en déduit qu’il doit gérer
le TLS pour
cdeper.net. - Il génère une paire de clés de compte ACME et s’enregistre auprès de Let’s Encrypt.
- Il tente le challenge TLS-ALPN-01 sur le port 443. Si le 443 est joignable, aucun trafic HTTP n’est même nécessaire.
- En repli, il bascule sur HTTP-01 via le port 80.
- Le certificat obtenu est stocké dans son data directory, chiffré au repos.
Le point qui piège tout le monde : le challenge TLS-ALPN-01 a besoin du port 443, pas seulement du 80. Beaucoup de tutoriels n’ouvrent que le 80 « parce que c’est pour Let’s Encrypt » et se demandent pourquoi Caddy échoue.
Le renouvellement, la partie invisible
Caddy vérifie ses certificats deux fois par jour et renouvelle à 30 jours de l’expiration. Il n’y a pas de processus séparé, pas de timer systemd : c’est une goroutine dans le processus Caddy lui-même. Conséquence directe : si Caddy tourne, le renouvellement fonctionne. Le mode d’échec de Certbot — le service tourne, mais le timer de renouvellement est cassé — n’existe pas ici.
Le persistant, à ne pas oublier
La seule vraie erreur possible avec Caddy en conteneur, c’est d’oublier de persister son data directory. Sans volume, chaque redémarrage réémet un certificat, et tu atteins la limite de Let’s Encrypt (5 certificats identiques par semaine) en une après-midi de tests.
volumes:
- caddy_data:/data # certificats + clés de compte ACME — CRITIQUE
- caddy_config:/config
caddy_data contient tes clés privées : traite ce volume comme un secret.
Sauvegarde-le, ne le mets pas dans un bucket public, et ne le committe jamais.
Les en-têtes, tant qu’on y est
Le TLS chiffre le transport. Il ne dit rien au navigateur sur la manière de se comporter. Ces en-têtes, eux, le font :
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
Strict-Transport-Security mérite une nuance : le flag preload engage ton
domaine dans une liste codée en dur dans les navigateurs. C’est difficilement
réversible. Ne l’active que si tu es certain de vouloir du HTTPS sur ce domaine
et tous ses sous-domaines pour longtemps.
Le compromis, honnêtement
Caddy fait des choix à ta place, et c’est précisément sa valeur — et sa limite. Pour du tuning fin (rate limiting granulaire, WAF ModSecurity, mTLS avec des politiques complexes), Nginx reste plus expressif. Pour servir un site statique en HTTPS correct sans y penser, Caddy gagne à chaque fois. Choisis en fonction de ce que tu as réellement besoin de contrôler.