Un serveur hébergeant plusieurs sites clients a vu l’un d’entre eux afficher un avertissement de sécurité, alors que Certbot signalait bien, dans ses propres journaux, un renouvellement réussi la semaine précédente. Contradiction apparente : le certificat était considéré comme renouvelé côté Certbot, mais le certificat effectivement servi par nginx aux visiteurs restait l’ancien, expiré. Ce type de décalage entre « renouvelé » et « effectivement actif » constitue l’une des causes silencieuses les plus fréquentes d’expiration malgré une automatisation apparemment fonctionnelle.
Trois causes distinctes, indépendantes les unes des autres, peuvent chacune produire ce symptôme identique. Les identifier une par une évite de s’arrêter à la première explication plausible sans vérifier les autres.
Cause 1 : un hook post-renouvellement qui échoue silencieusement
Certbot exécute, après chaque renouvellement réussi, un hook (script) chargé de recharger le service concerné — typiquement systemctl reload nginx. Si ce hook échoue (permissions insuffisantes de l’utilisateur exécutant Certbot, chemin de script incorrect après une réorganisation serveur), Certbot journalise malgré tout le renouvellement du certificat lui-même comme réussi : le nouveau certificat existe bien sur le disque, mais nginx continue de servir l’ancien, chargé en mémoire depuis son dernier démarrage.
$ journalctl -u certbot.timer --since "-14 days" | grep -i hook
Sep 04 03:12:41 srv1 certbot[8842]: Hook '--deploy-hook' reload-nginx.sh
returned error code 1
La vérification consiste à exécuter manuellement le hook déclaré, en dehors de Certbot, pour observer l’erreur exacte plutôt que de la deviner :
sudo /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
echo "code retour : $?"

Cause 2 : des permissions qui empêchent nginx de lire le nouveau certificat
Le dossier /etc/letsencrypt/live/ contient des liens symboliques vers les fichiers réels du certificat, stockés dans /etc/letsencrypt/archive/. Une modification de permissions un peu trop restrictive sur ce second dossier — par exemple lors d’un durcissement système appliqué globalement sans distinction — peut empêcher le processus nginx (exécuté sous un utilisateur dédié, pas root) de lire le nouveau fichier, alors que Certbot lui-même, exécuté en root, ne rencontre aucun obstacle pour écrire ce même fichier.
ls -la /etc/letsencrypt/archive/exemple.fr/
-rw------- 1 root root 1834 Sep 4 03:12 fullchain5.pem
Un fichier lisible uniquement par root, alors que le processus nginx tourne sous www-data, empêche le rechargement effectif, sans qu’aucune erreur ne remonte du côté de Certbot puisque son propre travail — générer le certificat — s’est parfaitement déroulé.
Cause 3 : un renouvellement réussi mais jamais rechargé après un redémarrage manqué
Plus rare mais déjà rencontré : un hook de rechargement correctement exécuté, mais ciblant le mauvais service. Sur un serveur exécutant plusieurs instances nginx (par exemple une instance dans un conteneur, une autre directement sur l’hôte), un hook mal ajusté après une migration partielle vers des conteneurs peut recharger l’instance qui ne sert en réalité aucun trafic réel, laissant l’instance active inchangée.
La vérification qui distingue les trois causes
Une seule commande permet de distinguer rapidement ce qui est réellement servi de ce qui existe sur le disque, sans hypothèse :
echo | openssl s_client -connect exemple.fr:443 -servername exemple.fr 2>/dev/null \
| openssl x509 -noout -dates
Comparer la date affichée par cette commande à la date du fichier réellement présent dans /etc/letsencrypt/archive/ révèle immédiatement si le problème vient de la génération du certificat (cause improbable si Certbot ne signale aucune erreur) ou de son chargement effectif par le serveur web (les trois causes précédentes).
- Tester manuellement chaque hook de renouvellement en dehors de Certbot, pas seulement lire ses journaux
- Vérifier les permissions du dossier
archiveaprès tout durcissement système du serveur - Comparer systématiquement le certificat réellement servi à celui présent sur le disque
« Certbot dit que ça a marché » et « le certificat servi aux visiteurs est à jour » sont deux affirmations différentes ; seule la seconde compte vraiment.
En résumé
Un renouvellement Certbot journalisé comme réussi ne garantit pas, à lui seul, qu’un visiteur reçoive effectivement le nouveau certificat. Les hooks de rechargement, les permissions du dossier archive et l’identification précise du service actif méritent chacun une vérification distincte avant de conclure qu’un renouvellement s’est réellement propagé jusqu’au visiteur.