Un dimanche matin, un client nous a envoyé une capture d’écran laconique : un cadenas barré rouge, un avertissement de sécurité plein écran, un lien vers son site que plus aucun navigateur n’acceptait de charger normalement. Le certificat TLS avait expiré. Ce qui rendait la situation embarrassante, c’est que Certbot, l’outil qui gère habituellement le renouvellement automatique via Let’s Encrypt, était installé et son timer systemd bien actif depuis l’installation initiale, des mois plus tôt.
Un renouvellement automatique qui échoue silencieusement est pire qu’une absence totale d’automatisation : il donne un faux sentiment de sécurité pendant que le compte à rebours continue de tourner vers zéro.
Symptôme : un cadenas barré malgré une automatisation en place
Le certificat Let’s Encrypt en cause avait une durée de validité de quatre-vingt-dix jours, standard pour ce type de certificat gratuit. Certbot est censé tenter un renouvellement dès que la validité restante descend sous trente jours, via un timer systemd exécuté deux fois par jour. Sur ce serveur, le timer existait bien et s’exécutait, mais chaque tentative échouait sans qu’aucune notification ne parvienne à quiconque.
Diagnostic : remonter aux journaux de Certbot
La première commande à exécuter dans ce type de situation consiste à demander à Certbot lui-même l’historique de ses tentatives, plutôt que de deviner :
$ certbot certificates
$ journalctl -u certbot.timer --since "-30 days"
$ cat /var/log/letsencrypt/letsencrypt.log | tail -n 100
Les journaux révélaient quatre tentatives de renouvellement échouées sur le mois précédent, toutes avec la même erreur : le défi HTTP-01 utilisé par Certbot pour prouver la propriété du domaine ne parvenait plus à joindre le chemin /.well-known/acme-challenge/ attendu, renvoyant une erreur 404. Le certificat avait pourtant été renouvelé sans souci à plusieurs reprises auparavant sur ce même serveur.

La cause : un bloc de configuration nginx ajouté sans précaution
En creusant l’historique des modifications serveur, la cause est apparue : un bloc nginx ajouté quelques semaines plus tôt pour rediriger systématiquement le trafic HTTP vers HTTPS avait été écrit un peu trop largement, redirigeant également les requêtes vers /.well-known/acme-challenge/ avant qu’elles n’atteignent le fichier de challenge attendu par Certbot.
# Bloc fautif : redirige tout, y compris les challenges ACME
server {
listen 80;
server_name exemple.fr;
return 301 https://$host$request_uri;
}
Cette redirection globale empêchait toute vérification par Let’s Encrypt, dont les serveurs interrogent explicitement le port 80 en clair pour valider le défi HTTP-01, sans jamais suivre une redirection vers HTTPS pour ce chemin précis. Le correctif consiste à exclure ce chemin de la redirection, avant la règle générale :
server {
listen 80;
server_name exemple.fr;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
Correctif immédiat : renouveler manuellement puis vérifier
Une fois la configuration corrigée et nginx rechargé, un renouvellement forcé a permis de vérifier la correction sans attendre le prochain passage du timer :
sudo certbot renew --force-renewal --dry-run
sudo certbot renew --force-renewal
sudo systemctl reload nginx
Prévention : superviser l’échéance, pas seulement le service
La leçon principale n’était pas de blâmer Certbot, qui avait fait exactement ce qu’on lui demandait — journaliser un échec, sans plus. La leçon était de ne jamais faire confiance à une automatisation sans vérification indépendante de son résultat effectif.
- Ajout d’une sonde de supervision externe qui vérifie la date d’expiration réelle du certificat servi, indépendamment de Certbot
- Alerte automatique dès que la validité restante descend sous quatorze jours, avec envoi vers un canal consulté activement
- Test systématique de
certbot renew --dry-runaprès toute modification de la configuration du serveur web touchant les ports 80 ou 443
Une automatisation de sécurité qui échoue sans alerte n’est pas une automatisation, c’est une dette qui s’accumule en silence.
En résumé
Le cron tournait, le timer était actif, et pourtant le certificat a expiré : l’automatisation seule ne protège de rien sans une vérification de son résultat, indépendante du mécanisme lui-même. Depuis cet incident, chaque serveur du parc dispose d’une sonde qui contrôle directement la date d’expiration du certificat exposé aux visiteurs, la seule mesure qui compte réellement.