Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Mettre à jour, restaurer et rebooter Nginx

Par mis à jour le

Améliorer cette page

Logo NGINX

Mettre à jour un service derrière Nginx tient en une règle : on démarre la nouvelle génération à côté de l'ancienne, on vérifie qu'elle répond, on bascule par un reload, et on garde de quoi revenir. Un reload qui réussit ne prouve ni que le binaire a changé, ni que le bon certificat est publié, ni que le service reviendra après un redémarrage de la machine. Cette leçon s'adresse à une personne qui sait recharger Nginx et qui doit maintenant livrer, mesurer et restaurer. Elle enseigne ce que chaque geste remplace réellement, ce qu'il faut sauvegarder avant, et comment prouver le résultat depuis le client.

Un mot de vocabulaire sert dans toute la leçon : une génération est une version du service, déployée avec son propre port et son propre certificat. La bascule est l'instant où Nginx cesse d'envoyer les nouvelles requêtes à l'ancienne génération pour les envoyer à la nouvelle, et le retour arrière est la bascule inverse.

La leçon va du geste le plus léger, le reload, au plus lourd, la perte de la machine.

  • Distinguer un reload de configuration, un remplacement du binaire et un redémarrage de l'hôte.
  • Livrer une nouvelle génération du service sans interrompre le trafic court.
  • Mesurer ce que devient une connexion longue pendant la bascule.
  • Sauvegarder ce qui permet de revenir, puis restaurer avec le certificat de la bonne génération.
  • Prouver que le service redémarre seul avec la machine.

Vous recevez déjà du trafic HTTPS derrière Nginx et vous savez le valider et le recharger.

  • nginx -t, nginx -T et reload : Installer Nginx.
  • Un certificat servi par Nginx et son renouvellement par reload : Nginx TLS.
  • Le diagnostic d'une panne après changement : Diagnostiquer Nginx.
  • Lire une unité systemd : Les services systemd.
  • Une machine Debian 13 avec sudo, où Nginx 1.31.8 est installé depuis le dépôt de l'éditeur (nginx.org) à la version épinglée par le lab.

Reload, mise à jour du binaire, perte de l'hôte : que change chaque geste ?

Section intitulée « Reload, mise à jour du binaire, perte de l'hôte : que change chaque geste ? »

Un reload relit la configuration, un remplacement du binaire change le programme qui s'exécute, et le redémarrage de la machine (la forme la plus courante de perte de l'hôte) relance tout depuis le disque : ce sont trois événements différents, et aucun ne dispense des deux autres. Les confondre est la source de la plupart des mises à jour qui « passent » sans rien changer.

GesteCe qui changeCe qui ne change pas
systemctl reload nginxConfiguration, certificats lus au chargementLe binaire en mémoire, le processus maître
Remplacement du binaireLe programme et ses modulesLa configuration (elle est conservée)
Redémarrage de la machineTout est relancé depuis le disqueRien en mémoire

Le tableau se lit de gauche à droite : la colonne du milieu dit ce qu'on obtient, la dernière ce qui reste inchangé et qu'il faut donc traiter à part. Après une mise à jour du paquet, le processus peut encore exécuter l'ancien binaire : le lien /proc/<PID>/exe du maître affiche alors (deleted) quand le fichier a été remplacé (c'est un comportement du noyau Linux, décrit dans la page de manuel proc_pid_exe(5), pas une fonction de Nginx), et nginx -v donne la version installée, pas celle qui tourne. La mise à jour à chaud du binaire existe (elle passe par le signal USR2 envoyé au maître, décrit dans la documentation de nginx.org), mais selon les scripts du paquet, une montée de version peut aussi relancer le service : prévoyez-la comme une coupure possible et mesurez-la. Le dépôt de l'éditeur publie environ une fois par mois sur la branche mainline : monter de version est un geste courant, qui se prépare par la recette ci-dessous plutôt que par l'improvisation.

Enfin, deux workers (les processus qui traitent les requêtes, sous la conduite du maître) ne sont pas deux domaines de panne, c'est-à-dire deux éléments dont l'un peut tomber sans entraîner l'autre. Ils partagent le même maître, la même machine, la même configuration : si le disque, la machine ou la configuration tombe, ils tombent ensemble. Augmenter le nombre de workers améliore le parallélisme, pas la disponibilité.

On vérifie la version cible, les modules, les certificats et les directives utilisées avant de toucher au service, parce qu'une directive absente de la version cible fait échouer la validation ou, pire, se comporte autrement. Le lab installe Nginx 1.31.8 depuis le dépôt de l'éditeur, à la version épinglée : lisez les notes de la version cible avant de monter, car une directive dépréciée reste acceptée sans être la forme à écrire, par exemple le paramètre http2 de listen, remplacé par la directive http2 on; que détaille la leçon Nginx flux longs. Une directive inconnue de la version cible est refusée par nginx -t, et c'est heureux : le refus arrive avant la coupure.

Quatre contrôles servent de recette avant et après chaque changement.

  • nginx -v et nginx -V donnent la version et les options de compilation, dont les modules présents.
  • sudo nginx -t valide la syntaxe, et sudo nginx -T affiche la configuration que le processus lira vraiment.
  • Les certificats dont nginx -T donne les chemins (ssl_certificate, ssl_certificate_key) : leurs dates et leur empreinte se lisent avec openssl x509 -noout -dates -fingerprint -sha256 -in <fichier>.
  • La recette métier : une requête par route, depuis un client, avec le contenu attendu et non seulement un code 200.

Rejouez cette recette avant pour avoir un point de comparaison, puis après : sans mesure de départ, on ne sait pas ce qui a changé.

On sauvegarde la configuration complète, les certificats et leurs clés avec leurs droits, les surcharges d'unité systemd et la version du paquet : sans elles, un retour arrière devient une reconstruction. Avec le paquet de nginx.org, la configuration vit sous /etc/nginx/ : le fichier principal nginx.conf et le répertoire conf.d/, dont nginx.conf inclut les fichiers *.conf. Les certificats et clés, eux, peuvent se trouver n'importe où : seul nginx -T donne leurs chemins réels. Une sauvegarde qui oublie la clé privée ne restaure rien.

Fenêtre de terminal
# La liste des fichiers de certificat réellement utilisés
sudo nginx -T 2>/dev/null | grep -E 'ssl_certificate(_key)?[[:space:]]'
# Archive de la configuration, droits conservés (-p), vers un répertoire de votre choix
sudo tar -cpzf <répertoire-de-sauvegarde>/nginx-etc.tar.gz /etc/nginx
# Version installée du paquet, à noter pour pouvoir y revenir
apt-cache policy nginx

La première commande donne les fichiers de certificat à ajouter à l'archive ; adaptez <répertoire-de-sauvegarde>, qui doit se trouver hors de /etc/nginx. L'option -p garde les modes, ce qui compte pour une clé en 0600. apt-cache policy affiche la version installée et les versions disponibles : notez la première, car revenir à une version de paquet n'est possible que si le dépôt la propose encore. Si une surcharge existe sous /etc/systemd/system/nginx.service.d/, ajoutez-la : elle modifie la façon dont le service démarre.

Une dernière précaution porte sur les fichiers de configuration modifiés à la main : lors d'une mise à jour du paquet, dpkg (l'outil qui installe les paquets sous Debian) peut demander s'il faut conserver votre version ou prendre celle du paquet (selon les options d'APT, la question peut ne pas être posée). Si elle l'est, gardez la vôtre, puis comparez avec diff ; la nouvelle version de référence reste consultable à côté.

Comment livrer une nouvelle génération sans couper le trafic ?

Section intitulée « Comment livrer une nouvelle génération sans couper le trafic ? »

On démarre la nouvelle génération sur son propre port, on attend qu'elle réponde, on fait pointer le proxy dessus, on valide, puis on recharge : l'ancienne n'est retirée qu'à la livraison suivante. Chaque génération a son port et son certificat, donc les deux peuvent tourner en même temps, et c'est ce qui rend atteignable une bascule sans erreur. Arrêter l'ancienne avant de démarrer la nouvelle ouvre une fenêtre que rien ne referme.

Séquence d'une livraison. L'opérateur démarre la génération 1.5.0 sur son port, attend une réponse saine, pointe l'upstream de Nginx sur cette génération et son certificat, puis lance nginx -t et reload. Nginx envoie les nouvelles connexions à la génération 1.5.0 pendant que les anciens workers finissent les flux en cours sur la génération 1.4.2, retirée seulement à la livraison suivante.Génération1.5.0Génération1.4.2NginxOpérateurles anciensworkers finissentles flux en coursretirée à lalivraisonsuivantedémarre sur son portattend une réponse sainepointe l'upstream sur1.5.0 et son certificatnginx -t puis reloadnouvelles connexions
Démarrer, attendre, basculer, recharger : l'ancienne génération survit jusqu'à la livraison suivante. Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Suivez l'ordre des flèches : la nouvelle génération est prête avant que le proxy ne la désigne, et le reload est la dernière étape, pas la première. Le mécanisme du reload (maître conservé, nouveaux workers, anciens workers qui terminent) est décrit dans Installer Nginx. Le geste complet s'écrit en un exécutable rejouable (livrer <version> dans le lab), qui rend la main quand la nouvelle génération est réellement servie, et qui est idempotent : le relancer avec la même version donne le même état final et ne casse rien.

Deux valeurs lues par le client, jamais celles du disque, disent si la livraison a réussi. La version servie : curl -sk --resolve <nom>:443:<IP> https://<nom>/version. L'empreinte du certificat publié, lue dans la poignée de main :

Fenêtre de terminal
echo | openssl s_client -connect <IP>:443 -servername <nom> 2>/dev/null \
| openssl x509 -noout -fingerprint -sha256

La commande affiche une ligne sha256 Fingerprint= suivie de l'empreinte : comparez-la à celle de la génération attendue. Dès que deux générations portent le même nom de service, seule l'empreinte dit laquelle est publiée.

Ce que le client lit dépend de la façon dont Nginx lit le certificat. Avec un chemin fixe dans ssl_certificate, il le lit au chargement de la configuration : un changement de fichier n'est donc visible qu'après le reload. Seul un chemin construit avec des variables (possible depuis la 1.15.9) est relu à chaque poignée de main, et ce n'est pas le cas dans le lab.

Que devient une connexion longue pendant un reload ?

Section intitulée « Que devient une connexion longue pendant un reload ? »

Une connexion déjà établie reste servie par les anciens workers jusqu'à sa fin ; seules les nouvelles connexions vont aux nouveaux workers. Un reload ne coupe donc pas un flux long (téléchargement, flux d'événements, WebSocket), tandis qu'un restart coupe toutes les connexions. La différence ne se voit que sur un flux long : sur du trafic court, les deux ressemblent à une réussite.

Deux limites se mesurent plutôt qu'elles ne se supposent. D'abord, un ancien worker qui garde un flux ouvert reste en vie : ps le montre avec la mention worker process is shutting down, et la directive worker_shutdown_timeout (apparue en 1.11.11) permet de borner ce temps : à l'échéance, Nginx tente de fermer les connexions encore ouvertes, ce qui coupe les flux qui le dépassent. La documentation n'en donne aucune valeur par défaut : ne supposez pas de limite, et un worker peut rester tant qu'un flux reste ouvert. Ensuite, recharger le proxy ne protège pas contre l'arrêt du backend : si la livraison arrête l'ancienne génération, les flux qu'elle servait sont coupés quand même. C'est pour cela que l'ancienne génération reste active jusqu'à la livraison suivante. Pour les flux eux-mêmes, voir Nginx flux longs.

Mesurez avec trois relevés pendant la livraison : le nombre de requêtes courtes en échec sur une série continue, l'état du flux long ouvert avant la bascule (continue-t-il de recevoir ?), et le temps pendant lequel d'anciens workers subsistent. Écrivez ces résultats et votre conclusion dans un court journal de livraison. Une série sans échec ne prouve pas qu'une absence de coupure est garantie partout : elle décrit cette livraison, sur cette machine, avec ce trafic.

Comment revenir en arrière avec le bon certificat ?

Section intitulée « Comment revenir en arrière avec le bon certificat ? »

Un retour arrière est une livraison à l'envers : il remet le code, la configuration et le certificat de la génération précédente, et il a besoin de savoir d'où il vient. Le piège est de ne ramener que le code. Si les deux générations portent le même nom de service, un retour qui oublie le certificat n'a l'air de rien : le service répond, le nom est bon, et seule l'empreinte dit que le certificat est celui de la génération qu'on vient de retirer.

La mémoire de la génération précédente doit être écrite à un endroit qui survit au redémarrage. Les répertoires /run et /tmp sont vidés au démarrage ; /var/lib ne l'est pas : on y crée donc un sous-répertoire pour cette mémoire. Un revenir (l'exécutable de retour arrière du lab) qui lirait son état dans /tmp fonctionnerait jusqu'au premier reboot, puis ne saurait plus où revenir.

Pour restaurer la configuration depuis l'archive faite plus haut, extrayez-la, puis validez avant de recharger, jamais l'inverse : sudo tar -xpzf <archive> -C /, puis sudo nginx -t && sudo systemctl reload nginx. Pour restaurer le paquet, installez la version notée (sudo apt install nginx=<version>, si le dépôt la propose encore ; lisez la liste des paquets qu'apt propose de modifier avant de confirmer), puis relancez la recette complète : version, modules, certificat, routes. Après un retour, vérifiez la version servie et l'empreinte, pas la seule absence d'erreur.

Comment prouver que tout survit à un redémarrage de la machine ?

Section intitulée « Comment prouver que tout survit à un redémarrage de la machine ? »

Un service livré n'est pas un service lancé : il doit revenir seul après un redémarrage, sans une commande de plus. systemctl enable programme le démarrage au boot, systemctl start le lance maintenant : les deux sont distincts, et un service seulement démarré disparaît au premier reboot. Vérifiez les deux états pour Nginx et pour chaque service de la pile :

Fenêtre de terminal
systemctl is-enabled nginx
systemctl is-active nginx

La première commande doit répondre enabled, la seconde active. Pour une pile qui compte une unité par génération, une unité modèle (unite@instance.service) évite de dupliquer les fichiers : l'identifiant d'instance y est disponible sous %i. Le test final se fait en redémarrant la machine, puis en rejouant la recette sans rien toucher. Il ne se remplace pas par un systemctl restart : seul un vrai redémarrage vérifie l'ordre de démarrage, les droits et les dossiers vidés au boot.

Cinq erreurs reviennent, et chacune a un contrôle qui la rend visible.

  • Prendre un reload réussi pour une mise à jour du binaire. Comparez la version installée et la version qui tourne.
  • Croire que deux workers donnent de la disponibilité. Ils partagent la machine, le maître et la configuration.
  • Arrêter l'ancienne génération avant de démarrer la nouvelle. La fenêtre d'indisponibilité n'a rien qui la ferme.
  • Revenir sans le certificat. Comparez l'empreinte, pas le nom.
  • Stocker l'état du retour arrière dans /tmp. Il disparaît au reboot.

Dans le lab, un service est publié en TLS derrière Nginx dans sa génération 1.4.2, et une seconde génération, 1.5.0, est déjà sur le disque, chacune avec son port et son certificat. Vous écrivez deux exécutables, livrer <version> et revenir, dans le langage de votre choix, et vous tenez un journal de vos mesures. La validation joue vos exécutables dans l'ordre du plan et mesure entre chaque appel : elle lit la version servie et l'empreinte du certificat depuis le client, vérifie qu'au plus une requête échoue sur une sonde continue pendant la bascule, que le flux long ouvert avant la bascule continue de recevoir après, que le journal existe et parle du flux long, que revenir ramène 1.4.2 avec son certificat, et que la recette passe après un redémarrage de la machine sans intervention.

Une mise à jour se prouve depuis le client, jamais depuis le disque.

  • Un reload relit la configuration ; il ne remplace pas le binaire et ne protège pas du redémarrage de la machine.
  • Le dépôt de l'éditeur publie une version mainline environ chaque mois : une montée de version se prépare par une recette, nginx -t refuse ce que la version cible ne connaît plus.
  • Avant de changer : nginx -v, nginx -t, nginx -T, les certificats et une recette par route.
  • Sauvegardez /etc/nginx avec ses droits, les certificats et clés dont nginx -T donne les chemins, les surcharges d'unité et la version du paquet.
  • Livrez en démarrant la nouvelle génération à côté, en attendant sa réponse, puis en rechargeant ; l'ancienne reste jusqu'à la livraison suivante.
  • Un flux long survit à un reload mais pas à l'arrêt de son backend ; mesurez-le, ne le supposez pas.
  • Un retour arrière ramène le code et le certificat, et garde sa mémoire sous /var/lib, pas sous /tmp.
  • enable n'est pas start : seul un vrai redémarrage de la machine prouve que le service revient seul.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

8 questions
8 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn