Vous avez exécuté certbot renew. Il a indiqué « success ». Votre monitoring continue pourtant d’alerter « certificat expire dans 2 jours ».
Vous vérifiez le système de fichiers et le nouveau certificat est bien présent. Pourtant les navigateurs affichent toujours l’ancien — parfois depuis la même machine.
Ce n’est pas un mystère. Il s’agit d’un ensemble de modes d’échec très prévisibles : mauvais chemin, mauvais bloc serveur, pas de rechargement,
un load balancer qui gère le TLS en amont, ou un processus obsolète qui n’a jamais rouvert les fichiers. Sur Ubuntu 24.04 les choix par défaut
sont raisonnables, mais l’écosystème autour (Snap, systemd, multiples instances Nginx, conteneurs) facilite l’erreur faite avec assurance.
Ce qui se passe réellement quand « renouvelé » ≠ « servi »
Deux systèmes distincts sont en jeu :
- Émission/renouvellement du certificat : un client ACME (généralement Certbot, parfois lego/acme.sh) écrit de nouveaux fichiers sur le disque.
- Diffusion TLS : Nginx lit les fichiers de certificat en mémoire lorsqu’il charge la configuration (démarrage ou rechargement). Il ne « voit » pas magiquement de nouveaux octets sur le disque.
Le mode d’échec est donc simple : le renouvellement a réussi, mais la pile de diffusion n’a pas basculé.
La partie délicate est que « la pile de diffusion » n’est pas forcément le processus auquel vous pensez. Il peut s’agir de :
Nginx sur l’hôte, Nginx dans un conteneur, Nginx dans un chroot, une seconde instance Nginx liée au port 443,
un reverse proxy en amont, ou un load balancer cloud terminant le TLS avant même que le trafic n’atteigne Nginx.
Une nuance supplémentaire : parfois Nginx est rechargé correctement, mais il sert toujours le « mauvais » certificat parce que la sélection SNI choisit un bloc serveur différent de celui attendu.
C’est fréquent quand vous avez un serveur par défaut, des certificats wildcard, ou un bloc catch-all laissé par un outil d’automatisation.
Votre objectif n’est pas « renouveler le certificat ». C’est la partie facile. Votre objectif est : prouver quel processus répond au TLS pour un nom d’hôte donné, et prouver quels fichiers il a chargés.
Blague n°1 : Les certificats sont comme le lait — la fraîcheur compte, mais personne ne veut être celui qui les renifle en production à 2 h du matin.
Fiche de diagnostic rapide (premier/deuxième/troisième)
Premier : confirmez ce que voient réellement les clients
- Depuis une machine externe à votre réseau (ou en utilisant une sonde publique), vérifiez le certificat présenté pour le nom d’hôte exact.
- Notez l’émetteur, le numéro de série, et les dates notBefore/notAfter.
- Si c’est l’ancien, ne touchez pas encore à Certbot. Le serveur sert d’anciens octets ; le renouvellement peut déjà être bon sur le disque.
Deuxième : identifiez qui termine le TLS
- Le port 443 sur l’hôte est-il vraiment Nginx ?
- Y a-t-il un load balancer, CDN, WAF, ou contrôleur d’ingress qui gère le TLS avant Nginx ?
- Y a-t-il plus d’une instance de Nginx (hôte + conteneur) ?
Troisième : corrélez config Nginx → chemin du certificat → fichier sur disque → processus chargé
- Trouvez le bloc
serverqui correspond au nom SNI. - Vérifiez les chemins
ssl_certificateetssl_certificate_key. - Vérifiez s’il s’agit de symlinks Let’s Encrypt
live/ou s’ils pointent versarchive/de façon fixe. - Rechargez Nginx et revérifiez depuis l’extérieur.
- Si le rechargement ne change rien, vous rechargez le mauvais Nginx ou la mauvaise config.
C’est l’ordre pour traquer le goulot. Commencez par ce que voient les utilisateurs, puis remontez. Ne commencez pas par suivre les logs de Certbot.
C’est ainsi qu’on perd une heure à prouver la mauvaise chose.
Faits et contexte intéressants (pourquoi ce problème revient)
- Fait 1 : Nginx ne relit pas automatiquement les fichiers de certificat sur le disque. Il les charge au démarrage et lors d’un
reload(rechargement de configuration gracieux). - Fait 2 : Les certificats Let’s Encrypt sont de courte durée (généralement 90 jours), par conception, pour réduire la portée d’un compromis de clé.
- Fait 3 : Certbot maintient deux répertoires :
/etc/letsencrypt/archive(fichiers versionnés) et/etc/letsencrypt/live(symlinks vers « current »). - Fait 4 : Une panne étonnamment courante est « renouvellement réussi, mais rechargement échoué ». Le log de renouvellement dit OK ; Nginx a continué de servir l’ancien certificat pendant des jours.
- Fait 5 : À l’époque early du TLS, certains serveurs nécessitaient un redémarrage complet pour changer le certificat ; le rechargement gracieux est devenu une fonctionnalité de fiabilité pratique, pas seulement un confort.
- Fait 6 : SNI (Server Name Indication) permet à une IP de servir plusieurs certificats. Si la sélection SNI tombe sur le mauvais bloc serveur, vous obtenez le mauvais certificat même si le bon existe.
- Fait 7 : L’adoption de Certbot empaqueté en Snap par Ubuntu a déplacé des emplacements de fichiers pour les logs et a parfois changé la façon dont les hooks de renouvellement s’exécutent, surtout en mélangeant apt et snap.
- Fait 8 : Le stapling OCSP peut rendre le débogage confus : les clients peuvent mettre en cache ou afficher l’état de stapling séparément de la chaîne de certificats, donc « ça semble faux » n’est pas toujours lié au fichier de certificat.
Causes principales : d’où vient vraiment l’ancien certificat
1) Nginx n’a jamais été rechargé (ou le rechargement a échoué)
Certbot peut renouveler sans redémarrer quoi que ce soit. Nginx continue de fonctionner et sert ce qu’il a chargé la semaine précédente.
Si vous avez un hook de déploiement qui devrait recharger Nginx, il peut ne pas être configuré, ne pas s’exécuter, ou échouer.
Pire encore : nginx -s reload peut réussir mais vous rechargez un binaire différent ou une instance différente de celle liée au 443.
2) Nginx pointe vers le mauvais chemin de fichier
Le modèle correct est de référencer /etc/letsencrypt/live/yourname/fullchain.pem et privkey.pem.
Si quelqu’un a codé en dur /etc/letsencrypt/archive/yourname/fullchain2.pem, cela n’avancera jamais automatiquement.
Ça fonctionne jusqu’au jour où ça ne fonctionne plus. C’est le classique « marche jusqu’à la prochaine rotation ».
3) Mauvais bloc serveur sélectionné (mauvais SNI)
Vous pouvez avoir le bon certificat dans un bloc serveur, et un bloc serveur par défaut avec un certificat obsolète.
Les clients atteignant example.com reçoivent le bon certificat ; ceux atteignant www.example.com ou un nom d’API reçoivent le défaut.
Ou votre vérificateur de santé utilise une adresse IP et aucun SNI, donc il cible toujours le défaut. Vous « corrigez » alors la mauvaise chose.
4) Le TLS est terminé ailleurs
Si vous utilisez un load balancer cloud, un CDN, un reverse proxy, ou un ingress Kubernetes, Nginx peut ne pas délivrer le TLS du tout.
Le renouvellement sur le backend est alors sans rapport ; la porte d’entrée a toujours l’ancien certificat.
Les pannes les plus coûteuses sont celles où tout le monde débogue la mauvaise couche avec un grand enthousiasme.
5) Multiples instances Nginx, conteneurs ou ports
Ubuntu 24.04 peut parfaitement exécuter :
Nginx sur l’hôte (systemd), Nginx dans Docker (compose), et un contrôleur d’ingress (Kubernetes).
Si deux processus écoutent sur 443 sur différentes interfaces réseau (ou un sur le réseau hôte, un derrière NAT), vous pouvez recharger le mauvais pendant des heures.
6) Permissions ou changements de format de clé
Certbot peut renouveler mais écrire des clés avec des permissions que Nginx ne peut pas lire (moins courant avec les chemins standards de Let’s Encrypt, plus courant avec des hooks personnalisés ou des fichiers copiés).
Ou vous êtes passé de RSA à ECDSA, changé les noms de fichiers, et oublié de mettre à jour la configuration Nginx. Le rechargement échoue alors et Nginx garde l’ancienne configuration en mémoire.
Tâches pratiques : commandes, sorties et décisions (12+)
Voici les vérifications que j’exécute réellement quand la production dit « certificat ancien ». Chaque tâche inclut :
la commande, ce que signifie la sortie, et la décision à en tirer.
Task 1: Check the served certificate from the outside (SNI on)
cr0x@server:~$ openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -serial
subject=CN = example.com
issuer=C = US, O = Let's Encrypt, CN = R11
notBefore=Dec 1 00:12:34 2025 GMT
notAfter=Feb 29 00:12:33 2026 GMT
serial=03A1B2C3D4E5F6
Signification : C’est ce que voient les clients. La date notAfter vous indique si c’est ancien.
Décision : Si c’est encore l’ancienne date d’expiration, poursuivez le diagnostic. Si c’est nouveau, votre monitoring vérifie peut-être un autre nom d’hôte ou point de terminaison.
Task 2: Check served certificate without SNI (default server behavior)
cr0x@server:~$ openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
subject=CN = default.invalid
notBefore=Sep 2 10:00:00 2025 GMT
notAfter=Dec 1 10:00:00 2025 GMT
Signification : Sans SNI, Nginx choisit le serveur par défaut pour cette IP:port.
Décision : Si le certificat par défaut est obsolète, corrigez aussi le bloc serveur par défaut, ou corrigez les clients/vérifications pour qu’ils envoient le SNI.
Task 3: Confirm which process is listening on 443
cr0x@server:~$ sudo ss -ltnp | grep ':443 '
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=2147,fd=6),("nginx",pid=2146,fd=6))
Signification : Vous voyez quel binaire possède la socket.
Décision : Si ce n’est pas Nginx (ou pas celui que vous pensez), arrêtez et traquez ce processus. Ne rechargez pas le mauvais.
Task 4: Ensure you’re reloading the same Nginx that’s running
cr0x@server:~$ ps -fp 2147
UID PID PPID C STIME TTY TIME CMD
root 2147 1 0 Dec28 ? 00:00:02 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
Signification : Confirme le chemin (/usr/sbin/nginx) et que systemd le gère probablement.
Décision : Utilisez systemctl reload nginx pour cette instance ; n’appelez pas un autre binaire nginx depuis une image de conteneur.
Task 5: Validate Nginx configuration before reloading
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Signification : Le rechargement réussira probablement. Si ceci échoue, Nginx refusera de charger les nouveaux chemins de certificats.
Décision : Corrigez les erreurs de configuration d’abord. Si nginx -t échoue, le « reload » n’actualisera pas les certificats.
Task 6: Reload Nginx and confirm systemd accepted it
cr0x@server:~$ sudo systemctl reload nginx
cr0x@server:~$ systemctl status nginx --no-pager -l
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-12-28 09:10:12 UTC; 1 day 3h ago
Docs: man:nginx(8)
Process: 33910 ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload (code=exited, status=0/SUCCESS)
Signification : Le rechargement a été exécuté et s’est terminé avec succès.
Décision : Revérifiez le certificat servi depuis l’extérieur. Si rien n’a changé, vous regardez le mauvais terminateur TLS ou le mauvais bloc serveur.
Task 7: Find which server block matches your hostname
cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -nE 'server_name|listen 443|ssl_certificate'
415: listen 443 ssl http2;
416: server_name example.com www.example.com;
432: ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
433: ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
601: listen 443 ssl;
602: server_name _;
612: ssl_certificate /etc/ssl/certs/old-default.pem;
613: ssl_certificate_key /etc/ssl/private/old-default.key;
Signification : Vous avez au moins deux blocs TLS : un correct, un par défaut avec un certificat ancien.
Décision : Mettez à jour le bloc par défaut (ou supprimez-le) si des clients peuvent y tomber. Assurez-vous aussi que chaque nom d’hôte est couvert par un server_name explicite.
Task 8: Verify the live/ symlinks actually point to the newest files
cr0x@server:~$ sudo ls -l /etc/letsencrypt/live/example.com/
total 4
-rw-r--r-- 1 root root 692 Sep 2 10:00 README
lrwxrwxrwx 1 root root 42 Dec 28 09:05 cert.pem -> ../../archive/example.com/cert12.pem
lrwxrwxrwx 1 root root 43 Dec 28 09:05 chain.pem -> ../../archive/example.com/chain12.pem
lrwxrwxrwx 1 root root 47 Dec 28 09:05 fullchain.pem -> ../../archive/example.com/fullchain12.pem
lrwxrwxrwx 1 root root 45 Dec 28 09:05 privkey.pem -> ../../archive/example.com/privkey12.pem
Signification : Nginx devrait référencer ces symlinks. Certbot fait pivoter leurs cibles.
Décision : Si Nginx pointe directement vers archive/, changez-le pour live/ afin que les futurs renouvellements n’exigent pas d’édition manuelle.
Task 9: Inspect on-disk cert dates (what renewal actually produced)
cr0x@server:~$ sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates -issuer -subject
notBefore=Dec 28 09:05:11 2025 GMT
notAfter=Mar 28 09:05:10 2026 GMT
issuer=C = US, O = Let's Encrypt, CN = R11
subject=CN = example.com
Signification : Le fichier sur disque est nouveau.
Décision : Si le disque est à jour mais que le certificat servi est ancien, le problème vient du rechargement/SNI/terminateur TLS, pas du renouvellement.
Task 10: Check Certbot renewal history and whether a deploy hook ran
cr0x@server:~$ sudo grep -R "Deploying certificate" -n /var/log/letsencrypt/letsencrypt.log | tail -n 3
2025-12-28 09:05:12,345:INFO:Deploying certificate to /etc/letsencrypt/live/example.com/fullchain.pem
2025-12-28 09:05:12,346:INFO:Deploying key to /etc/letsencrypt/live/example.com/privkey.pem
2025-12-28 09:05:12,900:INFO:Running deploy-hook command: systemctl reload nginx
Signification : Certbot a renouvelé et tenté un rechargement.
Décision : S’il n’y a pas de ligne deploy-hook, ajoutez-en une. Si elle existe, vérifiez qu’elle a réussi dans le journal système.
Task 11: Verify the Certbot timer (Ubuntu 24.04 systemd scheduling)
cr0x@server:~$ systemctl list-timers --all | grep -E 'certbot|letsencrypt'
Sun 2025-12-29 06:18:00 UTC 10h left Sat 2025-12-28 06:18:01 UTC 13h ago snap.certbot.renew.timer snap.certbot.renew.service
Signification : Le renouvellement est planifié (ici via l’unité Snap).
Décision : S’il n’existe aucun timer, le renouvellement ne se fera pas automatiquement. Si un timer existe mais que vous avez utilisé apt certbot, vous pouvez avoir deux configurations concurrentes — choisissez-en une.
Task 12: Confirm which Certbot you’re using (Snap vs apt) to avoid split-brain
cr0x@server:~$ which certbot
/snap/bin/certbot
cr0x@server:~$ snap list certbot
Name Version Rev Tracking Publisher Notes
certbot 2.11.0 3741 latest/stable certbot* classic
Signification : Vous utilisez Certbot via Snap.
Décision : Assurez-vous que tous les hooks, logs et attentes correspondent au packaging Snap. Évitez de mélanger avec un Certbot installé via apt sauf si vous aimez l’archéologie judiciaire.
Task 13: Find out if you’re behind a load balancer or proxy doing TLS
cr0x@server:~$ curl -sI https://example.com | grep -iE 'server:|via:|x-forwarded|cf-|x-amz'
server: cloud-proxy
via: 1.1 edge-gw
x-forwarded-proto: https
Signification : Les en-têtes suggèrent une couche proxy. Ce n’est pas une preuve, mais une forte odeur.
Décision : Vérifiez votre DNS et le chemin réseau. Si le TLS est terminé en amont, mettez à jour le certificat là-bas, pas sur Nginx.
Task 14: Check Nginx error logs for reload/cert read failures
cr0x@server:~$ sudo tail -n 30 /var/log/nginx/error.log
2025/12/28 09:05:13 [notice] 2147#2147: signal process started
2025/12/28 09:05:13 [emerg] 2147#2147: cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory)
Signification : Le rechargement a été tenté mais n’a pas réussi à lire le fichier. Nginx gardera l’ancienne config active.
Décision : Corrigez le chemin du fichier, les permissions, ou les contraintes SELinux/AppArmor (AppArmor est plus courant sur Ubuntu). Puis rechargez à nouveau.
Task 15: Prove which certificate file the running Nginx worker has open
cr0x@server:~$ sudo lsof -p 2147 | grep -E 'fullchain|cert\.pem|privkey' | head
nginx 2147 root mem REG 252,0 4231 131072 /etc/letsencrypt/live/example.com/fullchain.pem
nginx 2147 root mem REG 252,0 1704 131073 /etc/letsencrypt/live/example.com/privkey.pem
Signification : C’est le plus proche que vous obtiendrez de « ce que Nginx a chargé » du point de vue de l’OS.
Décision : Si cela pointe toujours vers un ancien fichier d’archive ou un domaine différent, corrigez la config et rechargez. Si c’est correct mais que les clients voient l’ancien, la terminaison TLS est ailleurs.
Task 16: Confirm your hostname resolves to the box you’re debugging
cr0x@server:~$ dig +short A example.com
203.0.113.10
cr0x@server:~$ ip -brief address show | awk '{print $1,$3}'
lo 127.0.0.1/8
eth0 203.0.113.10/24
Signification : L’enregistrement DNS A correspond à l’IP de l’hôte.
Décision : Si le DNS pointe ailleurs (ou si vous êtes derrière anycast/LB), vous déboguez la mauvaise machine. Cela arrive plus souvent qu’on l’admet.
Trois mini-récits du monde corporate
Mini-récit 1 : L’incident causé par une fausse hypothèse
Une société de taille moyenne pensait avoir une configuration « simple » : une VM, un Nginx, un domaine. Du moins, c’est ce que tout le monde croyait.
Ils ont renouvelé un certificat Let’s Encrypt sur Ubuntu, rechargé Nginx, et ont quand même reçu des alertes d’expiration.
L’ingénieur d’astreinte a supposé que le monitoring était erroné parce que certbot certificates affichait une nouvelle expiration.
Le navigateur sur son portable montrait aussi l’ancien certificat. Puis c’est devenu plus étrange : un collègue sur un autre FAI voyait le nouveau.
Cette différence a déclenché la première bonne question : « Sommes‑nous derrière un réseau edge ? »
Il s’est avéré que le service marketing avait récemment activé une fonctionnalité CDN/WAF gérée dans le tableau de bord du fournisseur DNS.
Le TLS était terminé à la périphérie avec un certificat uploadé que personne n’avait fait pivoter.
L’« hypothèse erronée » n’était pas une incompétence technique ; c’était organisationnel. Tout le monde supposait que le diagramme d’architecture de l’an dernier était encore valide.
En pratique, le système avait évolué sans qu’aucune PR n’affecte Nginx.
Renouveler le certificat backend n’a rien fait parce que le backend n’était plus le point de terminaison TLS.
La correction a été ennuyeuse : faire pivoter le certificat là où le TLS était terminé, le documenter, et ajouter une sonde qui vérifie le certificat depuis plusieurs réseaux.
La prévention était encore plus ennuyeuse : une revue hebdomadaire « qu’est‑ce qui a changé dans nos réglages edge ? ».
Personne n’aime ça, mais ça vaut mieux que d’apprendre les changements d’architecture via un pager.
Mini-récit 2 : L’optimisation qui s’est retournée contre eux
Une autre équipe voulait « réduire les rechargements » sur une flotte Nginx très sollicitée. Ils pensaient qu’un rechargement trop fréquent provoquerait des pics de latence.
Ils ont désactivé les hooks de rechargement automatique après renouvellement et prévu de recharger pendant une fenêtre de maintenance hebdomadaire.
L’idée semblait raisonnable : moins de rechargements, moins de complexité.
Deux mois plus tard, ils ont atteint le constat prévisible : le renouvellement a réussi plusieurs fois, mais les processus en cours ne se sont jamais rechargés.
Certains serveurs avaient été redémarrés pour des raisons non liées et servaient des certificats frais ; d’autres non, et servaient des certificats périmés.
La flotte est devenue un patchwork de dates d’expiration. Le monitoring est passé d’un signal propre à du bruit.
La douleur opérationnelle venait de l’ambiguïté. Quand un nom d’hôte a commencé à échouer les handshakes TLS pour une partie des utilisateurs, les ingénieurs ne savaient pas s’il s’agissait d’un problème réseau,
d’un nœud spécifique, ou d’un cache client. Ils ont passé des heures à rassembler des preuves qui menaient toutes à une phrase : « notre optimisation a créé une dérive d’état. »
Ils ont annulé le changement : restauration des deploy hooks, rechargements automatiques, et mesurer l’impact au lieu de l’assumer.
Bien exécutés, les rechargements Nginx sont gracieux. Ils ne coupent pas les connexions ; ils démarrent de nouveaux workers et drainent les anciens.
Le problème n’était pas que les rechargements soient intrinsèquement dangereux. Le problème était de traiter la cohérence opérationnelle comme optionnelle.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une entreprise régulée exécutait Nginx sur Ubuntu avec un processus de changement strict. Tout le monde se plaignait des checklists.
Mais ils avaient une pratique qui ressemblait à de la bureaucratie et agissait comme une assurance : un job de vérification post‑renouvellement.
Après chaque renouvellement, un job exécuté depuis l’extérieur enregistrait le numéro de série et l’expiration du certificat servi dans un log central.
Un matin, le job a signalé qu’un seul nom d’hôte VIP servait encore un ancien certificat. Tout le reste semblait sain.
L’équipe n’a pas paniqué ; ils avaient un playbook. Première vérification : SNI. Deuxième : serveur par défaut. Troisième : listeners du load balancer.
Ils ont trouvé un listener legacy sur le load balancer qui utilisait encore un certificat uploadé au lieu du certificat géré.
La correction a pris quelques minutes parce que les preuves étaient immédiates et spécifiques : « ce listener présente le numéro de série X ; attendu Y ».
Pas de débat, pas d’archéologie de captures d’écran, pas de « ça marche sur mon laptop ».
Une demande de changement a été approuvée rapidement car c’était une substitution simple, pas une chirurgie exploratoire.
La morale est agressivement non romantique : vérifiez ce que voient les utilisateurs, automatiquement, après chaque rotation.
C’est le type de pratique qui fait que les ingénieurs se sentent sous‑estimés — jusqu’au jour où elle prévient une panne.
Erreurs courantes : symptôme → cause → correction
1) « Certbot dit renouvelé, mais les navigateurs montrent encore l’ancienne expiration »
Cause : Nginx ne s’est pas rechargé, ou le rechargement a échoué.
Correction : Lancez sudo nginx -t ; ensuite sudo systemctl reload nginx. Vérifiez systemctl status nginx et /var/log/nginx/error.log. Ajoutez un deploy hook pour que cela se fasse automatiquement.
2) « Le certificat sur le disque est nouveau, mais le servi est ancien — seulement pour certains noms d’hôtes »
Cause : Mismatch SNI/bloc serveur. Un bloc serveur par défaut ou un autre server_name capture le trafic.
Correction : Utilisez openssl s_client -servername pour chaque nom d’hôte. Inspectez nginx -T pour listen 443 et server_name. Assurez-vous que chaque hôte correspond au bon certificat.
3) « Les health checks disent que le certificat est ancien, mais les utilisateurs normaux vont bien »
Cause : Le vérificateur de santé n’envoie pas le SNI et cible le serveur/certificat par défaut.
Correction : Configurez le checker pour utiliser le nom d’hôte (SNI) ou corrigez le certificat du serveur par défaut pour qu’il soit valide pour ce point d’IP.
4) « Le rechargement réussit mais rien ne change »
Cause : Vous avez rechargé un Nginx différent de celui qui sert le 443, ou le TLS est terminé en amont.
Correction : Confirmez la propriété de la socket avec ss -ltnp. Confirmez que le DNS pointe vers cette machine. Si un load balancer/CDN existe, faites pivoter le certificat là-bas.
5) « Après le renouvellement, Nginx ne se recharge pas ; il continue de servir l’ancien certificat »
Cause : Les nouveaux fichiers sont absents/inaccessibles à cause de permissions, coquilles dans les chemins, ou références incorrectes (par ex. référencer chain.pem au lieu de fullchain.pem dans certaines configurations).
Correction : Vérifiez /var/log/nginx/error.log pour cannot load certificate. Corrigez les chemins, permissions, et référencez fullchain.pem. Relancez nginx -t.
6) « Seuls quelques clients voient l’ancien certificat ; d’autres voient le nouveau »
Cause : Multiples nœuds edge / enregistrements A multiples / anycast / pool de load balancer incohérent.
Correction : Résolvez le DNS depuis plusieurs emplacements ; vérifiez chaque nœud backend individuellement ; assurez-vous du renouvellement et du rechargement partout ; corrigez la dérive.
7) « Nous avons mis à jour la config Nginx vers le nouveau chemin de certificat, mais elle a été revert plus tard »
Cause : Gestion de configuration ou l’installateur Nginx de Certbot a écrasé les fichiers.
Correction : Gérez les directives TLS dans votre source de vérité (Ansible, Puppet, etc.) et évitez les modifications manuelles de snippets générés sans propriété claire.
Blague n°2 : Rien ne construit l’alignement d’équipe comme un certificat qui expire — soudainement tout le monde se souvient qui possède le DNS.
Listes de vérification / plan étape par étape
Étape par étape : corriger la situation « renouvelé mais toujours ancien » en toute sécurité
- Prouvez le symptôme depuis l’extérieur. Utilisez
openssl s_client -servernameet enregistrez l’expiration + le numéro de série. - Prouvez qui possède :443. Utilisez
ss -ltnp. Si ce n’est pas Nginx, arrêtez et orientez le ticket correctement. - Prouvez que le DNS pointe ici. Utilisez
dig +shortet comparez aux IP locales. - Inspectez la sélection de configuration Nginx. Utilisez
nginx -T, trouvez le bonserver_name, et identifiez les cheminsssl_certificate. - Assurez-vous de référencer les symlinks Let’s Encrypt
live/. Corrigez tout codage en dur versarchive/. - Validez la config. Lancez
nginx -t. Pas de validation, pas de rechargement. - Rechargez Nginx. Utilisez
systemctl reload nginx(ou votre gestionnaire de service) et confirmez le succès viasystemctl status. - Re-vérifiez depuis l’extérieur. Même commande, même nom d’hôte, confirmez que le numéro de série/l’expiration ont changé.
- Si inchangé, cherchez la terminaison upstream. Vérifiez les listeners LB/CDN et où les certificats sont gérés.
- Automatisez le prochain cas. Ajoutez un deploy hook et une vérification externe post-renouvellement.
Checklist : à quoi ressemble le « bon » sur Ubuntu 24.04
- La config TLS Nginx référence
/etc/letsencrypt/live/<name>/fullchain.pemetprivkey.pem. - Une seule pipeline d’autorité de certificats existe (Certbot Snap ou outils basés apt), pas les deux.
- Un timer systemd exécute le renouvellement régulièrement, et les logs montrent les deploy hooks en action.
- Le rechargement Nginx est testé (
nginx -t) et surveillé pour les échecs. - Une sonde externe vérifie le certificat servi après renouvellement et alerte sur les divergences.
Checklist : évitez ces mouvements « astucieux »
- Ne pointez pas Nginx vers
/etc/letsencrypt/archivesauf si vous aimez les rotations manuelles. - Ne « optimisez » pas en supprimant les hooks de rechargement. La dérive vous trouvera.
- Ne supposez pas qu’une VM sert le TLS simplement parce qu’elle exécute Nginx.
- Ne déboguez pas uniquement avec une capture d’écran de navigateur. Utilisez
opensslet capturez les numéros de série.
FAQ
1) Pourquoi Nginx ne prend‑il pas automatiquement les certificats renouvelés ?
Parce que Nginx lit les fichiers de certificat et de clé lorsqu’il charge la configuration. Le renouvellement modifie les fichiers sur le disque, pas l’état en mémoire de Nginx.
Il faut un rechargement (ou un redémarrage) pour rouvrir et parser les nouveaux fichiers.
2) Est‑ce que systemctl reload nginx est sûr en production ?
Généralement oui. Un rechargement est conçu pour être gracieux : de nouveaux workers démarrent avec la nouvelle config, les anciens drainent.
Exécutez quand même nginx -t avant ; une config cassée transforme le « sûr » en « incident auto‑infligé ».
3) Quelle est la différence entre fullchain.pem et cert.pem ?
cert.pem contient uniquement le certificat leaf. fullchain.pemfullchain.pem est le choix standard pour Nginx.
4) Pourquoi je vois le nouveau certificat sur le disque mais un ancien sur le réseau ?
Soit Nginx ne s’est pas rechargé, soit Nginx pointe vers des fichiers différents de ceux que vous avez inspectés, soit le point de terminaison TLS n’est pas Nginx (load balancer/CDN).
Traitez cela comme un problème de routage/propriété jusqu’à preuve du contraire.
5) Mon monitoring dit « certificat expire bientôt », mais openssl s_client montre un certificat récent. Qui a tort ?
Peut‑être personne. Le monitoring peut vérifier un autre nom d’hôte, vérifier sans SNI, vérifier une ancienne IP, ou vérifier une autre région/edge.
Mettez à jour la vérification pour envoyer le SNI et valider le nom d’hôte exact touché par les utilisateurs.
6) Puis‑je simplement redémarrer Nginx au lieu de recharger ?
Vous pouvez, mais le rechargement est généralement une meilleure habitude : moins de perturbations et moins d’effets secondaires surprises.
Le redémarrage est un outil brutal ; utilisez‑le quand le rechargement est bloqué (par exemple, workers coincés) ou quand votre gestionnaire de processus l’exige.
7) Et si j’utilise un load balancer qui termine le TLS ?
Alors renouveler le certificat backend n’affectera pas ce que voient les utilisateurs. Faites pivoter le certificat sur le load balancer (ou activez les certificats gérés là‑bas).
Vous pouvez garder le TLS backend pour la défense en profondeur, mais ne le confondez pas avec le certificat public.
8) Comment éviter que cela se reproduise ?
Deux choses : (1) un deploy hook qui recharge Nginx après un renouvellement réussi, et (2) une vérification externe qui confirme le numéro de série/l’expiration servi.
L’automatisation sans vérification n’est qu’un échec rapide.
9) Quel est le signal unique auquel vous faites confiance en débogage ?
Le certificat réellement servi à un client réel, mesuré avec SNI via openssl s_client (ou une sonde équivalente) et enregistré avec numéro de série + expiration.
Tout le reste est preuve d’appui.
Conclusion : étapes suivantes pour éviter la réapparition
Ce problème est rarement « Let’s Encrypt a échoué ». C’est presque toujours « la couche de diffusion n’a pas basculé ». Votre diagnostic doit en tenir compte.
Commencez par l’extérieur, prouvez ce qui est servi, prouvez qui le sert, puis alignez les chemins de config et le comportement de rechargement.
Le principe opérationnel se résume par une idée souvent attribuée à Ronald Coase : si vous torturez suffisamment les données, elles finiront par avouer
.
En termes d’opérations : ne torturez pas les logs et les hypothèses. Mesurez le point de terminaison live, puis remontez.
Prochaines étapes pratiques :
- Standardisez Nginx pour référencer
/etc/letsencrypt/live/.../fullchain.pemetprivkey.pem, pasarchive/. - Faites de
nginx -t+systemctl reload nginxl’action post‑renouvellement via un deploy hook. - Ajoutez une sonde externe qui enregistre le numéro de série et l’expiration du certificat servi par nom d’hôte après un renouvellement.
- Auditez vos points de terminaison TLS : VM, ingress conteneur, load balancer, CDN. Assignez un propriétaire à chacun.