
NixOS est une distribution Linux dont la particularité tient en une phrase : le système entier se déclare dans des fichiers. Le bootloader, les services, les utilisateurs, les paquets, tout est décrit, et une commande construit le système correspondant. Chaque construction produit une génération conservée à côté des précédentes, ce qui rend le retour arrière atomique et rapide. Cette page définit NixOS sans le vendre, montre ce que le rollback répare et ce qu'il ne répare pas, expose les pièges serveur mesurés en laboratoire, et se termine par un lab d'installation en VM KVM pour vous faire votre propre avis.
Tout ce qui suit a été rejoué sur une machine réelle en NixOS 26.05 « Yarara » (release nixos-26.05.4659.8f0500b96605, noyau 6.18.38, Nix 2.34.7, bootloader systemd-boot). Les sorties de commandes affichées sont celles de cette machine, pas des reconstitutions.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Définir NixOS en termes concrets : système déclaré, store, générations, rollback atomique
- Distinguer ce que NixOS garantit vraiment de ce que le marketing lui prête (la reproductibilité bit-à-bit n'est pas la promesse)
- Mesurer les limites du rollback : un seul cran, pas les fichiers de conf, pas les données
- Identifier les pièges serveur : secrets en clair, RAM,
/boot, absence de LTS, perte d'accès SSH - Décider si NixOS a sa place chez vous, ou si c'est un mauvais investissement dans votre contexte
- Installer NixOS 26.05 dans une VM KVM avec flakes et disko, et jouer un premier rollback
NixOS en une page : ce que c'est, ce que ça change
Section intitulée « NixOS en une page : ce que c'est, ce que ça change »Sur une distribution classique, l'état du système est le résultat d'une histoire : les paquets installés, les fichiers édités, les services activés, dans l'ordre où on l'a fait. Personne ne connaît cette histoire en entier, et deux serveurs censés être identiques finissent par diverger. C'est la dérive de configuration.
NixOS renverse le raisonnement. Vous ne décrivez pas des actions, vous décrivez un état cible. Le fichier configuration.nix dit ce que la machine doit être, nixos-rebuild se charge de l'y amener. Ajouter un serveur web se résume à une ligne.
services.nginx.enable = true;Un nixos-rebuild switch plus tard, le paquet est installé, la configuration générée, l'unité systemd créée, activée et démarrée. Aucun apt install, aucun systemctl enable, aucun fichier édité à la main. Retirez la ligne, rebuildez : le service, son utilisateur système et sa configuration disparaissent.
Le store : là où tout est rangé
Section intitulée « Le store : là où tout est rangé »Chaque paquet et chaque configuration système vivent dans /nix/store/, sous un chemin préfixé par un hash calculé à partir de toutes les entrées de la construction (code source, dépendances, options de compilation). Deux versions d'un même paquet ont deux chemins et cohabitent sans conflit : il n'y a pas d'écrasement, donc pas d'installation « par-dessus ». Ce répertoire est monté en lecture seule, et c'est la garantie structurelle de tout le modèle.
mount | grep -E "on / | /nix/store"# /dev/vda2 on / type ext4 (rw,relatime,x-initrd.mount)# /dev/vda2 on /nix/store type ext4 (ro,nosuid,nodev,relatime)Le mécanisme du store, des profils et des générations est détaillé dans le guide Nix store, profils et générations. Retenez ici la conséquence, qui est le point le plus mal compris de NixOS : ce qui n'est pas dans le store n'est pas versionné, donc n'est pas rollbackable.
Les générations : un point de restauration par construction
Section intitulée « Les générations : un point de restauration par construction »Chaque nixos-rebuild switch produit une génération : un lien vers une closure complète du store, conservé à côté des précédentes. Le système actif est celui vers lequel pointe /run/current-system.
nixos-rebuild list-generations# Generation Build-date NixOS version Kernel Current# 2 2026-07-12 22:19:29 26.05.4659.8f0500b96605 6.18.38 True# 1 2026-07-12 22:04:49 25.11.12484.b6018f87da91 6.12.93 FalseChaque génération dépose aussi son noyau et son initrd dans /boot, plus une entrée pour le bootloader. C'est ce qui permet de redémarrer sur un système d'il y a trois semaines, avec son propre noyau. C'est aussi ce qui fait grossir /boot, et le piège associé est traité plus bas.
Le bénéfice réel : configuration reproductible, pas reproductibilité bit-à-bit
Section intitulée « Le bénéfice réel : configuration reproductible, pas reproductibilité bit-à-bit »C'est la nuance qui sépare un guide honnête d'une plaquette commerciale. Les hashes de Nix portent sur les entrées de la construction (le graphe de dépendances), pas sur les octets produits en sortie : un paquet dont la compilation embarque un horodatage donnera deux binaires différents pour un même hash d'entrée. Dire que « NixOS garantit des builds reproductibles bit à bit » est faux, et l'exagération est régulièrement démontée en public.
Ce que NixOS garantit vraiment, et qui suffit largement à justifier son existence, tient en deux points : la même configuration redonne le même système déployé, et le retour en arrière est atomique. Vérifié en rejouant le lab deux fois de bout en bout : à configuration identique, les chemins du store obtenus sont les mêmes, au caractère près.
Ce que NixOS n'est pas
Section intitulée « Ce que NixOS n'est pas »NixOS n'est pas un système « immuable » au sens de Fedora Silverblue ou Talos, où l'on remplace une image système signée. Ici, l'immuabilité vient du store en lecture seule et de la régénération complète de /etc à chaque activation, pas d'une image scellée : la page Systèmes d'exploitation immuables situe les deux approches. Ce n'est pas non plus un gestionnaire de paquets que l'on poserait sur Debian : ça, c'est Nix, traité dans la section dédiée. NixOS est ce qui arrive quand on pousse Nix jusqu'au système d'exploitation entier.
« Si ça build, ça marche » : c'est faux
Section intitulée « « Si ça build, ça marche » : c'est faux »Voici l'affirmation qu'on lit partout : sur NixOS, une configuration invalide est attrapée à la construction, donc elle ne peut pas casser la production. C'est faux, et le lab le prouve en une manipulation. Il faut distinguer deux classes d'erreurs, et une seule des deux est réellement interceptée.
Classe 1 : l'erreur d'évaluation, attrapée avant que rien ne bouge
Section intitulée « Classe 1 : l'erreur d'évaluation, attrapée avant que rien ne bouge »Vous vous trompez dans le nom d'une option. L'évaluation échoue immédiatement, avant toute construction et avant toute activation. Aucune génération n'est créée, le système ne bouge pas d'un pouce, et NixOS va jusqu'à suggérer la correction.
error: The option `services.nginx.enabel' does not exist. Definition values: - In `/etc/nixos/configuration.nix': trueDid you mean `services.nginx.enable', `services.nginx.gitweb' or `services.nginx.user'?C'est le filet dont tout le monde parle, et il est réel. Une faute de frappe dans un nom d'option ne peut pas atteindre la production.
Classe 2 : l'erreur de contenu, qui passe le build et casse l'activation
Section intitulée « Classe 2 : l'erreur de contenu, qui passe le build et casse l'activation »Maintenant, injectez une directive invalide dans une chaîne libre passée à un service. Ici, services.nginx.appendHttpConfig reçoit une directive nginx qui n'existe pas. Nix ne connaît pas la grammaire de nginx : pour lui, c'est du texte.
Le résultat est sans appel : le build réussit, la génération est créée, et c'est l'activation qui explose.
restarting the following units: nginx.serviceFailed to restart nginx.serviceCommand 'systemd-run [...] switch-to-configuration switch' returned non-zero exit status 4.Le journal montre que c'est le pré-démarrage de l'unité qui refuse la configuration, une fois le système déjà basculé.
nginx-pre-start[6693]: nginx: [emerg] unknown directive "directive_qui_nexiste_pas" in /nix/store/zl8...-nginx.conf:28systemd[1]: Failed to start Nginx Web Server.État résultant, mesuré : systemctl is-active nginx répond activating, curl http://localhost renvoie une connexion refusée, le site est down, et nixos-rebuild list-generations affiche bien la nouvelle génération. Le système a basculé sur une configuration qui ne fonctionne pas.
Un détail gênant mérite d'être signalé tel quel : l'option services.nginx.validateConfigFile vaut true par défaut (vérifié avec nixos-option sur la machine), et la configuration invalide a quand même été construite. Un nginx -t lancé à la main sur le fichier produit dans le store la rejette pourtant sans ambiguïté. Ce lab n'a pas élucidé pourquoi la validation au build n'a pas joué, et il serait malhonnête d'inventer une explication.
Ce que ce contre-exemple doit changer dans votre pratique
Section intitulée « Ce que ce contre-exemple doit changer dans votre pratique »La leçon n'est pas « NixOS est dangereux ». La leçon est que le vrai filet de sécurité n'est pas le build, c'est le rollback. Toute configuration qui passe une chaîne libre à un service (nginx, PostgreSQL, sshd, systemd) échappe à la validation de Nix, parce que Nix ne parle pas ces langages. Deux réflexes en découlent :
nixos-rebuild testavantswitchsur les changements sensibles : la configuration est activée mais ne devient pas le défaut au démarrage. Un simple reboot ramène le système connu.- Savoir rollbacker de tête, sans chercher la commande. Elle prend 2 secondes, c'est l'opération la plus rapide de tout NixOS.
Le rollback : rapide, spectaculaire, et plus limité qu'on ne le dit
Section intitulée « Le rollback : rapide, spectaculaire, et plus limité qu'on ne le dit »Le rollback est le geste emblématique de NixOS, et il tient ses promesses. Une commande, deux secondes, et le système redevient exactement ce qu'il était. Voici la sortie réelle après avoir ajouté puis retiré nginx.
sudo nixos-rebuild switch --rollback# switching profile from version 2 to 1# stopping the following units: [...] nginx.service# removing user 'nginx'Vérification immédiate : systemctl status nginx répond Unit nginx.service could not be found. et curl échoue avec Failed to connect to localhost port 80. Le service a réellement disparu, avec son utilisateur système. Rien n'a été « désinstallé » : le système a simplement réactivé une closure du store qui n'a jamais cessé d'exister.
Ce mécanisme est excellent. Il a quatre limites, et toutes les quatre coûtent cher le jour où on les découvre en production.
Limite 1 : --rollback ne recule que d'un seul cran
Section intitulée « Limite 1 : --rollback ne recule que d'un seul cran »Beaucoup de billets écrivent « revenez à n'importe quelle génération avec --rollback ». C'est faux. L'option recule d'exactement une génération, celle qui précède l'actuelle. Deux appels successifs donnent, dans le lab : switching profile from version 11 to 10, puis from version 10 to 9. Pour viser une génération arbitraire, il faut passer par le lien du profil correspondant, ce que détaille le guide dédié.
Limite 2 : le rollback annule le système, pas le fichier
Section intitulée « Limite 2 : le rollback annule le système, pas le fichier »Après un --rollback, votre configuration.nix contient toujours la ligne fautive. Le système est sain, le fichier ne l'est pas : les deux ont divergé. Le prochain nixos-rebuild switch que fera un collègue, pour une raison sans rapport, remettra la panne. Le rollback est une opération sur le profil système, pas sur votre dépôt.
Limite 3 : le garbage collector détruit le rollback, et laisse un menu menteur
Section intitulée « Limite 3 : le garbage collector détruit le rollback, et laisse un menu menteur »nix-collect-garbage sans option libère de la place sans toucher aux générations (410 Mio récupérés dans notre lab). Avec -d, il supprime les anciennes racines, et le filet disparaît.
nixos-rebuild switch --rollback# error: no profile version older than the current (11) existsLe piège dans le piège est plus vicieux. Juste après le -d, /boot/loader/entries/ contient toujours les 11 fichiers, dont ceux des générations qui viennent d'être détruites. Le menu de démarrage propose donc des entrées qui ne démarreront pas : le chemin du store qu'elles référencent n'existe plus. C'est le rebuild suivant qui nettoie l'ESP. Entre les deux, la machine expose un menu mensonger, et c'est précisément le moment où vous en auriez besoin.
Limite 4 : le rollback ne restaure pas les données
Section intitulée « Limite 4 : le rollback ne restaure pas les données »C'est la limite la plus importante, et la moins écrite. Nous l'avons mise en scène avec PostgreSQL et une vraie base.
Une table commandes contient trois lignes. L'application fait une bêtise et les efface. Réflexe NixOS : je rollback, ça répare tout.
sudo -u postgres psql -d boutique -c "DELETE FROM commandes;"# DELETE 3
sudo nixos-rebuild switch --rollback# switching profile from version 26 to 25Le système est bien revenu en arrière : le chemin de /run/current-system est identique à celui d'avant. Et les lignes ?
sudo -u postgres psql -d boutique -c "SELECT * FROM commandes;"# id | client | montant# ----+--------+---------# (0 rows)Le système est revenu en arrière, les lignes non. Le rollback ne sauvegarde rien : il réactive une ancienne closure du store, point final. Il ne défait même pas un DELETE.
La preuve est structurelle, pas anecdotique. Un grep récursif du contenu applicatif dans /nix/store ne remonte aucune donnée : elles vivent dans /var/lib/postgresql/, hors du store, sur un système de fichiers en lecture-écriture, et le store est de toute façon monté en lecture seule. Ce qui n'est pas dans le store n'est pas versionné, donc n'est pas rollbackable. Un rollback n'est pas une sauvegarde : il ne remplace ni pg_dump, ni un snapshot ZFS, ni votre plan de reprise.
Le cas de la montée de version majeure est encore plus parlant. Passer de PostgreSQL 16.14 à 17.10 se fait en changeant une ligne de la configuration.
services.postgresql = { enable = true; package = pkgs.postgresql_17; # au lieu de postgresql_16};Le rebuild passe en 10 secondes, le service redémarre, SELECT version() annonce fièrement PostgreSQL 17.10. Sauf que le répertoire de données a changé de /var/lib/postgresql/16 à /var/lib/postgresql/17, que ce nouveau répertoire est vide, que PostgreSQL l'a donc initialisé de zéro, et que la base de l'application n'existe plus.
sudo -u postgres psql -d boutique -c "SELECT * FROM commandes;"# psql: error: [...] FATAL: database "boutique" does not existAucune erreur, aucun avertissement : un service actif, une base neuve, et vos données toujours sur le disque mais plus servies par personne. Le rollback vers 16 les retrouve intactes, ce qui est heureux, mais imaginez la scène si le garbage collector était passé entre-temps, ou si l'application avait écrit dans la base neuve. C'est exactement pourquoi l'option system.stateVersion existe, et pourquoi le manuel écrit que la plupart des utilisateurs ne devraient jamais y toucher : elle fige le choix de version des logiciels qui ne savent pas migrer leurs données tout seuls. Ce n'est pas un numéro de version à incrémenter, contrairement à ce que conseillent beaucoup de billets.
Le rollback, la sélection d'une génération dans systemd-boot, le mode rescue et le garbage collection sont traités scénario par scénario dans le guide dédié.
La question qui vient toujours : et si je mets ma conf dans Git ?
Section intitulée « La question qui vient toujours : et si je mets ma conf dans Git ? »C'est le réflexe de tout le monde, et c'est un bon réflexe. Versionner /etc/nixos dans un dépôt Git donne l'historique, la revue, le git revert, et l'impression rassurante d'avoir tout sous contrôle. Le lab a joué le scénario en entier, et la réponse est plus nuancée que « oui ».
Ce que Git règle, et ce qu'il ne règle pas
Section intitulée « Ce que Git règle, et ce qu'il ne règle pas »Git règle le problème du fichier, celui de la limite 2 ci-dessus. Après un rollback système, un git revert du commit fautif remet le dépôt d'accord avec le système : les deux cessent de diverger, et le nixos-rebuild switch d'un collègue ne réintroduit pas la panne. Git permet aussi de remonter loin, là où --rollback ne recule que d'un cran : cinq commits en arrière se retrouvent avec un git checkout.
En revanche, Git ne restaure pas les données. Votre dépôt décrit le système, pas le contenu de /var/lib. Toutes les conclusions de la section précédente restent valables telles quelles.
Le piège des canaux : la révision de nixpkgs n'est pas dans votre dépôt
Section intitulée « Le piège des canaux : la révision de nixpkgs n'est pas dans votre dépôt »Le scénario monté par le lab est déterminant. Une machine installée avec les canaux (le mécanisme historique, encore celui du manuel). Le dépôt est propre, on note le chemin du système au commit A. Le temps passe : le canal nixos-26.05 avance tout seul, un nix-channel --update récupère une nouvelle révision de nixpkgs. On ajoute un paquet, c'est le commit B.
Panne. On revient au commit A avec Git. Le fichier est exactement celui du commit A, diff le confirme. On rebuilde. Le système obtenu est-il celui du commit A ?
SA (rebuild du commit A à l'époque, canal 4494) : /nix/store/4v0bm1hz...-nixos-system-nixos-lab-26.05.4494.74cc63f702f7SA' (rebuild du commit A aujourd'hui, canal 4659) : /nix/store/6drz9k5y...-nixos-system-nixos-lab-26.05.4659.8f0500b96605==> DIFFERENTS : git seul NE SUFFIT PAS, la revision de nixpkgs vient du canal, pas du depotDeux systèmes différents, à partir du même commit. Les paquets ne sont plus les mêmes, le noyau non plus. Où vit la révision qui a changé ? Nulle part dans votre dépôt : dans le profil de canal, sous /nix/var/nix/profiles/per-user/root/channels/. Le verdict brut du lab est sans appel : aucun fichier du dépôt ne contient la révision de nixpkgs, c'est là qu'est la faille.
Avec une flake, le verrou est dans le dépôt
Section intitulée « Avec une flake, le verrou est dans le dépôt »Une flake est un format de projet Nix qui déclare ses dépendances (les inputs) et verrouille leurs révisions exactes dans un fichier flake.lock, comme un package-lock.json. La différence capitale avec les canaux : ce flake.lock est un fichier du dépôt, donc versionné avec le reste.
Le même scénario, rejoué sur une machine installée par flake : commit A avec un lock sur une révision, nix flake update qui fait avancer le lock, commit B, puis retour au commit A avec Git.
SA (commit A à l'époque) : /nix/store/njqz7kjd...-nixos-system-nixos-lab2-26.05.20260708.74cc63fSA' (commit A rebâti après update) : /nix/store/njqz7kjd...-nixos-system-nixos-lab2-26.05.20260708.74cc63f==> IDENTIQUES : Git + flake.lock redonnent EXACTEMENT le meme systemeLe même chemin du store, au hash près. La conclusion opérationnelle est simple et vaut d'être retenue : Git seul ne suffit pas, il faut Git plus un verrou de version. Sur une machine de production, c'est l'argument le plus solide en faveur des flakes, bien avant les considérations d'élégance.
Une réserve honnête : les flakes sont toujours officiellement expérimentales en 2026, alors même que 78,9 % des répondants à l'enquête communautaire 2025 les utilisent. Ce décalage a une conséquence concrète en entreprise : le mot « expérimental » bloque des validations sécurité, indépendamment de la qualité réelle du mécanisme. Il faut le savoir avant de bâtir une flotte dessus. Le mécanisme lui-même est expliqué dans Comprendre et utiliser les flakes Nix.
Les pièges serveur, mesurés
Section intitulée « Les pièges serveur, mesurés »Les douleurs de NixOS sur un poste de travail (pilotes NVIDIA, Steam, AppImage, Python scientifique) sont abondamment documentées, et elles disparaissent sur un serveur. Mais le serveur a ses propres pièges, moins racontés parce qu'ils se révèlent tard. Voici ceux que le lab a reproduits.
Un secret écrit dans un .nix finit en clair, lisible par tous
Section intitulée « Un secret écrit dans un .nix finit en clair, lisible par tous »C'est le piège le plus grave, parce qu'il est silencieux. /nix/store est lisible par tous les utilisateurs de la machine, par construction. Tout secret écrit dans un fichier .nix y atterrit en clair.
# Depuis un compte utilisateur ordinaire, sans aucun privilègegrep -rl MonMotDePasse123 /nix/store/ | head -2# /nix/store/66g24jlv...-users-groups.jsonUn utilisateur non privilégié relit le mot de passe. NixOS n'a pas de solution native à ce problème. La parade la plus simple est agenix, qui chiffre les secrets avec la clé SSH de l'hôte et ne les déchiffre qu'à l'activation. Vérifié sur la machine : après chiffrement, le grep dans le store ne trouve plus rien, et ce qui s'y trouve est un fichier .age chiffré. Le secret déchiffré, lui, atterrit dans /run/agenix/ avec des permissions -r-------- root:root (un compte ordinaire obtient Permission denied). Le point de montage mérite qu'on s'y arrête.
findmnt -no FSTYPE -T /run/agenix# ramfsUn ramfs, pas un tmpfs. La différence n'est pas cosmétique : un tmpfs peut être envoyé dans le swap, donc écrit sur disque, alors qu'un ramfs ne swappe jamais. Le secret déchiffré ne touche jamais le stockage persistant, et c'est exactement le genre de détail qui fait la différence dans une revue de sécurité.
Dernier avertissement : le secret qui a fuité avant la mise en place d'agenix est toujours dans le store, référencé par une ancienne génération, tant que celle-ci n'a pas été collectée. Un secret ayant fuité dans le store est à considérer comme compromis, donc à faire tourner.
La RAM : l'évaluation coûte cher, et la marge est nulle sur un petit VPS
Section intitulée « La RAM : l'évaluation coûte cher, et la marge est nulle sur un petit VPS »Chiffre rarement publié, et pourtant décisif pour qui déploie sur des VPS. Une simple réévaluation de la configuration, tout étant déjà en cache, sans rien à télécharger ni à compiler, consomme :
User time (seconds): 3.12Elapsed (wall clock) time: 0:04.02Maximum resident set size (kbytes): 606400606 Mo de mémoire résidente juste pour évaluer nixpkgs. Ce n'est pas un build : c'est le simple fait de calculer ce que le système devrait être. Avec une configuration plus fournie (nginx plus PostgreSQL), le pic monte à 632 Mo.
Nous avons délibérément joué la scène sur une VM à 1 Go (957 Mo réels, 706 Mo disponibles, aucun swap). Le verdict est plus nuancé que ce qu'on lit : le rebuild passe. Aucun OOM dans dmesg, le système reste debout, les services démarrent. Mais faites le calcul : 606 Mo consommés sur 706 disponibles, la marge est de 100 Mo. Ajoutez un second canal, une configuration plus riche ou un service qui mange déjà sa part, et vous basculez. Un administrateur ayant documenté le cas sur un VPS 1 Go mesure 500 Mo en configuration minimale, 700 Mo avec des services, 1,2 Go avec un second canal, et rapporte un OOM franc lors d'une montée de version.
La formulation juste est donc : un rebuild tient sur 1 Go avec une configuration minimale, mais la marge est nulle. Ce n'est pas une plateforme sur laquelle on veut être quand la production est en jeu.
La parade est structurelle, et c'est l'une des bonnes idées de NixOS : construisez ailleurs, déployez la closure. L'outil officiel nixos-rebuild le fait nativement avec --target-host : le poste d'administration évalue et construit, la cible se contente de recevoir des chemins du store et d'activer. Le lab l'a poussé jusqu'à l'absurde en supprimant tout canal nixpkgs de la cible : elle devient alors incapable d'évaluer quoi que ce soit, et le déploiement fonctionne quand même. La preuve est faite qu'elle n'a rien construit.
/boot qui sature, et la machine ne démarre plus
Section intitulée « /boot qui sature, et la machine ne démarre plus »Chaque génération pousse son noyau et son initrd dans la partition EFI. Sur notre montée de version, /boot est passé de 25 Mo à 64 Mo avec seulement deux générations, et le store de 2,0 Go à 4,2 Go. Multipliez par vingt générations, sur une ESP de 512 Mo dimensionnée par un installateur d'origine, et vous saturez.
Le problème n'est pas l'espace disque : c'est que le rebuild peut échouer en cours d'écriture dans /boot et laisser la machine avec zéro entrée de boot valide. Sur un serveur distant sans console, cela signifie un déplacement physique. L'issue nixpkgs#141399, « Unbootable system when /boot partition fills up during rebuild », est toujours ouverte. Le garde-fou existe, il n'est simplement pas activé par défaut : déclarez-le dès la première configuration d'un serveur, c'est une ligne et elle vous évitera une nuit blanche.
boot.loader.systemd-boot.configurationLimit = 10;Pas de LTS : sept mois de support, contre cinq ans chez Debian
Section intitulée « Pas de LTS : sept mois de support, contre cinq ans chez Debian »C'est le fait le plus structurant pour qui envisage NixOS en production, et il n'a rien de technique. NixOS sort deux versions par an (mai et novembre), chacune supportée environ sept mois. 26.05 « Yarara », sortie le 30 mai 2026, est maintenue jusqu'au 31 décembre 2026. 25.11 « Xantusia » est morte le 30 juin 2026 : 26.05 est aujourd'hui la seule version stable maintenue. Il n'existe aucune LTS, et un fil communautaire évoquant une LTS payante confirme en creux qu'il n'y en a pas de gratuite.
| NixOS | Debian | |
|---|---|---|
| Rythme de publication | 2 versions par an | environ tous les 2 ans |
| Support d'une version | environ 7 mois | 5 ans (avec le support long terme) |
| Montées de version imposées | 2 par an | 1 tous les 2 ans, planifiable |
Concrètement : deux montées de version majeures par an, non négociables. Si votre organisation peine déjà à passer une Debian tous les deux ans, NixOS sera un problème d'exploitation, quelles que soient ses qualités techniques. La comparaison avec un cycle long se mesure sur la page Debian 13 Trixie : ce qui change pour un serveur.
Pas de rollback automatique si vous perdez l'accès SSH
Section intitulée « Pas de rollback automatique si vous perdez l'accès SSH »Le rollback exige un accès à la machine. Déployez une configuration qui casse sshd, le pare-feu ou le réseau, et vous perdez cet accès : le filet est hors de portée, précisément quand vous en auriez besoin. Ce n'est pas un oubli mineur, l'issue nixpkgs#65477, « Request for fail-safe rollback », est ouverte depuis le 27 juillet 2019 et l'est toujours. nixos-rebuild n'offre aucun filet de ce type. La parade tient en une commande, et elle est gratuite.
sudo nixos-rebuild test --flake .#nixos-labtest active la nouvelle configuration mais ne la rend pas bootable par défaut. Si vous perdez la main, un simple redémarrage (bouton reset de l'hyperviseur, console cloud) ramène le système connu. Le lab a vérifié ce comportement avec deux redémarrages réels : après un test, le service ajouté est actif immédiatement, aucune génération ni entrée de boot n'est créée, et après reboot il a disparu. C'est le mode à utiliser sur tout changement qui touche l'accès à la machine.
Le binaire précompilé ne s'exécute pas, et le message a changé
Section intitulée « Le binaire précompilé ne s'exécute pas, et le message a changé »Vous téléchargez un agent de supervision, un EDR, un client de sauvegarde, un binaire fourni par un éditeur. Sur Debian, il tourne. Sur NixOS, non. La cause est que le chargeur dynamique standard (/lib64/ld-linux-x86-64.so.2) n'existe pas ici, et les binaires génériques le cherchent à un chemin en dur.
Attention aux vieux billets : le fameux cannot execute: required file not found n'est plus le message en 26.05. NixOS installe désormais un stub-ld qui explique le problème au lieu de le subir.
$ /root/ls-ubuntu /tmpCould not start dynamically linked executable: /root/ls-ubuntuNixOS cannot run dynamically linked executables intended for genericlinux environments out of the box. For more information, see:https://nix.dev/permalink/stub-ldDiagnostic : /lib64/ld-linux-x86-64.so.2 existe bien, mais c'est un leurre qui pointe vers ce stub, et /lib n'existe pas du tout.
La parade dominante est le module officiel nix-ld, qui recrée un vrai chargeur. Mais ne le vendez pas comme une case à cocher : programs.nix-ld.enable = true; ne suffit pas. Le chargeur est alors trouvé, et le binaire échoue aussitôt sur la bibliothèque suivante.
$ /root/ls-ubuntu /tmp/root/ls-ubuntu: error while loading shared libraries: libselinux.so.1: cannot open shared object fileIl faut déclarer explicitement les bibliothèques dont le binaire a besoin. Pour un simple /bin/ls d'Ubuntu, le jeu complet ressemble à ceci, et il a fallu deux itérations pour le trouver :
programs.nix-ld.enable = true;programs.nix-ld.libraries = with pkgs; [ libselinux pcre2 acl attr libcap zlib stdenv.cc.cc.lib];L'angle serveur est celui-ci : ce sont les agents (supervision, EDR, sauvegarde, agent d'un fournisseur) qui coincent, parce qu'ils supposent une arborescence Debian ou RedHat. Avant de choisir NixOS pour une flotte, faites l'inventaire des binaires propriétaires que vous devez y faire tourner. C'est souvent là que la décision se joue.
Le dépaysement : /usr, /etc, et un nginx qui ne sert aucune page
Section intitulée « Le dépaysement : /usr, /etc, et un nginx qui ne sert aucune page »Trois surprises attendent tout administrateur venant de Debian, et il vaut mieux les rencontrer dans un lab que sur un serveur.
D'abord, l'arborescence Unix n'existe presque plus. Il n'y a aucun gestionnaire de paquets classique, et les répertoires historiques sont vides : ls /usr renvoie bin, ls /usr/bin renvoie env, ls /bin renvoie sh. Deux rescapés, et rien d'autre, tous deux des liens vers le store. Ils survivent parce que trop de scripts au monde en dépendent.
Ensuite, /etc est régénéré à chaque activation. Le hotfix à trois heures du matin n'existe pas.
echo "hotfix-manuel" > /etc/hostname# bash: /etc/hostname: Read-only file systemMême en supprimant le lien pour écrire un vrai fichier, le nixos-rebuild switch suivant efface le hotfix et remet son lien vers /etc/static/. Il n'y a pas de correction rapide : il y a une modification de la configuration, un rebuild, et une trace dans Git. Selon votre culture d'équipe, c'est un soulagement ou une torture.
Enfin, la surprise la plus déroutante : services.nginx.enable = true; démarre bien le service (systemctl is-active nginx répond active), et pourtant rien n'écoute sur le port 80. curl échoue, ss -lntp ne montre aucun port en écoute : aucun hôte virtuel n'est déclaré par défaut, alors que sur Debian un apt install nginx sert immédiatement sa page d'accueil. Accessoirement, /etc/nginx/nginx.conf n'existe pas : la configuration vit dans le store, référencée par l'unité systemd. Chercher le fichier de configuration d'un service est un réflexe à désapprendre.
Monter de version : 25.11 vers 26.05, ce que ça donne
Section intitulée « Monter de version : 25.11 vers 26.05, ce que ça donne »Puisque 25.11 est morte et que la migration est obligatoire, autant la voir en vrai. Le lab a installé une VM en 25.11 « Xantusia » (noyau 6.12.93, Nix 2.31.5) et l'a fait monter par la procédure officielle : on change le canal, puis on reconstruit.
sudo nix-channel --add https://channels.nixos.org/nixos-26.05 nixossudo nix-channel --updatesudo nixos-rebuild switch --upgrade
nixos-version# 26.05.4659.8f0500b96605 (Yarara)
nixos-rebuild list-generations# 2 2026-07-12 22:19:29 26.05.4659.8f0500b96605 6.18.38 True# 1 2026-07-12 22:04:49 25.11.12484.b6018f87da91 6.12.93 FalseLa montée fonctionne, l'ancienne génération reste disponible, et un rollback ramène la 25.11 en une seconde et demie. Trois observations méritent d'être notées.
Le noyau ne change qu'au redémarrage : juste après le switch, nixos-version annonce 26.05 mais uname -r répond toujours 6.12.93. Après reboot, 6.18.38. C'est la raison d'être des générations dans le bootloader.
Le store double de volume, de 2,0 Go à 4,2 Go, parce que les deux versions cohabitent tant que le garbage collector n'est pas passé. Prévoyez la place sur une racine étriquée.
Enfin, system.stateVersion reste à 25.11, et c'est normal. Beaucoup de billets conseillent de le « bumper » : ne le faites pas. Ce n'est pas un numéro de version, c'est le marqueur qui dit avec quelle génération de logiciels vos données existantes ont été créées. Le modifier peut rendre vos bases illisibles. Dernière précision, qui vous évitera de chercher : en 26.05, nixos-rebuild est une réécriture complète en Python (nixos-rebuild-ng), l'implémentation Bash ayant été supprimée, et quelques options ont bougé (--sudo remplace --use-remote-sudo). Les tutoriels antérieurs à 2026 décrivent l'ancienne.
Pour qui c'est un bon choix, pour qui c'est un piège
Section intitulée « Pour qui c'est un bon choix, pour qui c'est un piège »Le moment de trancher. Ni promotion, ni dénigrement : NixOS est un excellent outil dans un périmètre précis, et un mauvais investissement en dehors.
| Situation | Verdict |
|---|---|
| Une flotte de serveurs à configuration homogène, gérée en équipe, avec revue de code | Bon choix. La configuration déclarative et le rollback atomique rendent la dérive impossible. |
| Environnements de développement et CI reproductibles | Bon choix, et c'est l'usage le plus répandu en entreprise (souvent avec Nix seul, sans NixOS). |
| Un poste d'administration ou un bastion à durcir et auditer | Bon choix. Tout est déclaré, donc tout est auditable. Le retour d'expérience Sécurix le démontre en conditions réelles. |
| Une seule machine, gérée par une personne | Probablement pas. La complexité ne se rentabilise pas sur un seul système. |
| Des agents propriétaires obligatoires (EDR, supervision, sauvegarde d'un éditeur) | Terrain miné. Chaque binaire non packagé est un chantier nix-ld ou une dérivation à écrire. |
| Une organisation qui ne sait pas monter de version tous les six mois | Piège. L'absence de LTS n'est pas contournable. |
| Une base de données critique, sans stratégie de sauvegarde propre | Piège dangereux. Le rollback donne une illusion de filet qu'il n'offre pas sur les données. |
La réserve la plus utile ne vient pas d'un détracteur, mais d'un utilisateur convaincu. Michael Stapelberg, développeur Debian et ancien ingénieur Google, a migré son NAS vers NixOS en juillet 2025. Il apprécie de gérer tout le système déclarativement et juge les modules NixOS d'un niveau d'abstraction supérieur aux conteneurs. Sa conclusion mérite d'être citée telle quelle :
if you have just a single system to manage, probably all of this is too complicated.
NixOS est un investissement dont le retour vient du nombre de machines et de la durée. Sur une seule machine, vous payez la complexité sans jamais toucher le dividende.
Un mot sur la maturité, pour finir. Le projet a traversé une crise de gouvernance en 2024 (démission du créateur du board, départs de mainteneurs, fork Lix), mais une nouvelle gouvernance a été élue en novembre 2024 : il n'est pas acéphale. Les critiques persistantes portent ailleurs, et l'enquête communautaire 2025 les chiffre : 47,6 % des utilisateurs réclament de meilleurs messages d'erreur, 41,5 % un meilleur manuel. Quand la moitié des convaincus demande ça, c'est structurel, et c'est ce qui rend la courbe d'apprentissage réellement raide.
Le lab : installer NixOS 26.05 dans une VM KVM
Section intitulée « Le lab : installer NixOS 26.05 dans une VM KVM »La meilleure façon de se faire un avis reste de poser le système sur une machine jetable et de le casser. Ce lab installe NixOS 26.05 dans une VM KVM, avec un partitionnement déclaratif via disko et une configuration pilotée par une flake. Comptez trente minutes, et vous pourrez tout détruire sans rien risquer.
Prérequis
Section intitulée « Prérequis »Avant de commencer, vérifiez que vous disposez de :
- Un poste Linux avec KVM/QEMU et libvirt (
virsh,virt-install) - Le firmware OVMF pour le boot UEFI (
/usr/share/OVMF/OVMF_CODE_4M.fdsur Debian et Ubuntu) - 8 Go de RAM à allouer à la VM d'installation
- 20 Go d'espace disque pour l'image QCOW2
- L'ISO NixOS 26.05 minimal (environ 1,6 Go)
- Une clé SSH existante sur l'hôte
Le point sur la RAM n'est pas une précaution de confort. Avec 4 Go, notre installation a échoué : l'ISO tient son store de travail dans un tmpfs dimensionné sur la mémoire vive, et l'évaluation de nixpkgs le sature.
error: write of 470 bytes: No space left on deviceerror: could not find a flake.nix fileLe message est trompeur (il parle d'espace disque alors que le problème est la RAM) et fait perdre beaucoup de temps. Allouez 8 Go pour l'installation. La VM installée, elle, tourne sans problème avec 2 Go.
Les trois fichiers du lab
Section intitulée « Les trois fichiers du lab »Le lab tient en trois fichiers, plus le verrou généré. Comprendre leur rôle respectif est plus important que de les recopier.
| Fichier | Rôle |
|---|---|
flake.nix | Point d'entrée : déclare les dépendances (nixpkgs, disko) et la configuration NixOS |
disko-config.nix | Schéma de partitionnement déclaratif du disque |
configuration.nix | Le système : bootloader, réseau, utilisateurs, paquets, services |
flake.lock | Les révisions verrouillées des dépendances (généré, mais à versionner) |
Le flake déclare deux choses : les inputs (ses dépendances, avec leurs versions) et les outputs (ce qu'il produit, ici une configuration nommée nixos-lab).
{ description = "NixOS Lab - VM KVM de test";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; };
outputs = { self, nixpkgs, disko }: { nixosConfigurations.nixos-lab = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ disko.nixosModules.disko ./disko-config.nix ./configuration.nix ]; }; };}La ligne inputs.nixpkgs.follows = "nixpkgs" force disko à utiliser la même version de nixpkgs que votre configuration. Sans elle, deux arborescences nixpkgs cohabitent en mémoire et l'évaluation coûte deux fois plus cher.
Disko décrit le partitionnement de manière déclarative, ce qui évite le fdisk manuel et le rend rejouable.
{ lib, ... }:{ disko.devices = { disk = { main = { type = "disk"; device = "/dev/vda"; content = { type = "gpt"; partitions = { ESP = { size = "512M"; type = "EF00"; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; mountOptions = [ "umask=0077" ]; }; }; root = { size = "100%"; content = { type = "filesystem"; format = "ext4"; mountpoint = "/"; }; }; }; }; }; }; };}Le device = "/dev/vda" correspond au disque virtio dans QEMU. Sur une machine physique, adaptez (/dev/nvme0n1, /dev/sda) et vérifiez deux fois : disko formate sans poser de question.
Vient enfin le cœur du système, où chaque ligne correspond à quelque chose de concret sur la machine.
{ config, pkgs, modulesPath, ... }:{ # Profil QEMU : charge les modules virtio dans l'initrd imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
# Bootloader UEFI boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true;
# Garde-fou contre la saturation de /boot boot.loader.systemd-boot.configurationLimit = 10;
# Modules noyau pour la virtualisation boot.initrd.availableKernelModules = [ "virtio_pci" "virtio_blk" "virtio_scsi" "ahci" "sd_mod" ]; boot.kernelModules = [ "virtio_net" ];
networking.hostName = "nixos-lab";
time.timeZone = "Europe/Paris"; i18n.defaultLocale = "fr_FR.UTF-8"; console.keyMap = "fr";
# SSH par clé uniquement services.openssh = { enable = true; settings = { PermitRootLogin = "prohibit-password"; PasswordAuthentication = false; }; };
users.users.lab = { isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAA... votre-cle-publique" ]; };
# Sudo sans mot de passe : VM de test UNIQUEMENT security.sudo.wheelNeedsPassword = false;
environment.systemPackages = with pkgs; [ vim git htop curl tmux ];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Garbage collection automatique nix.gc = { automatic = true; dates = "weekly"; options = "--delete-older-than 30d"; };
system.stateVersion = "26.05";}Quatre lignes méritent une explication, parce qu'elles font la différence entre un système qui démarre et un système qui ne démarre pas :
imports = [ qemu-guest.nix ]charge les modules virtio dans l'initrd. Sans elle, le noyau ne trouve pas le disque et vous restez bloqué surwaiting for device.configurationLimit = 10empêche/bootde se remplir indéfiniment. Ce n'est pas le défaut.security.sudo.wheelNeedsPassword = falseest acceptable sur une VM jetable et inacceptable ailleurs. Ne recopiez pas cette ligne sur un serveur.system.stateVersionest la version de NixOS à l'installation initiale. Elle protège vos données : ne la modifiez jamais après coup, même en montant de version.
L'anatomie de configuration.nix, l'exploration des options avec nixos-option, la factorisation en modules et la gestion des utilisateurs sont traitées dans le guide dédié.
Préparer la machine virtuelle
Section intitulée « Préparer la machine virtuelle »Récupérez l'ISO minimale de NixOS 26.05, puis créez le disque et la VM.
mkdir -p ~/lab-nixos/images && cd ~/lab-nixos/imageswget https://channels.nixos.org/nixos-26.05/latest-nixos-minimal-x86_64-linux.iso
qemu-img create -f qcow2 ~/lab-nixos/images/nixos-lab.qcow2 20GLe format QCOW2 est sparse : le fichier ne consomme que l'espace réellement utilisé. Le store d'un système fraîchement installé pèse 2,2 Go mesurés.
virt-install \ --name nixos-lab \ --ram 8192 \ --vcpus 4 \ --disk path=$HOME/lab-nixos/images/nixos-lab.qcow2,format=qcow2,bus=virtio \ --cdrom $HOME/lab-nixos/images/latest-nixos-minimal-x86_64-linux.iso \ --os-variant nixos-unstable \ --network network=default,model=virtio \ --graphics vnc,listen=127.0.0.1 \ --boot loader=/usr/share/OVMF/OVMF_CODE_4M.fd,loader.readonly=yes,loader.type=pflash,loader.secure=no \ --noautoconsoleVérification : virsh list --all doit montrer la VM en état running.
Installer NixOS
Section intitulée « Installer NixOS »L'ISO démarre sur un shell non privilégié : le compte est nixos, pas root. C'est la première chose qui surprend, et tout tutoriel qui enchaîne des commandes de partitionnement sans sudo échoue avec un Permission denied. Le compte nixos est dans le groupe wheel avec sudo sans mot de passe.
SSH, lui, refuse les connexions tant qu'aucun mot de passe n'est défini. Il faut en poser un temporairement via la console.
-
Définir un mot de passe sur l'installateur depuis l'hôte, en pilotant la console.
Fenêtre de terminal # Attendre ~40 secondes que l'ISO démarrevirsh send-key nixos-lab KEY_P KEY_A KEY_S KEY_S KEY_W KEY_D KEY_ENTERsleep 2for key in KEY_N KEY_I KEY_X KEY_O KEY_S; dovirsh send-key nixos-lab $key; sleep 0.3donevirsh send-key nixos-lab KEY_ENTERsleep 1for key in KEY_N KEY_I KEY_X KEY_O KEY_S; dovirsh send-key nixos-lab $key; sleep 0.3donevirsh send-key nixos-lab KEY_ENTERLe délai de 0,3 seconde entre les touches n'est pas décoratif : plus court (0,15 s), la console virtuelle perd des lettres et votre mot de passe n'est pas celui que vous croyez.
-
Se connecter à l'installateur après avoir récupéré l'adresse attribuée par DHCP.
Fenêtre de terminal virsh domifaddr nixos-labsshpass -p 'nixos' ssh -o StrictHostKeyChecking=no nixos@192.168.122.x -
Copier les trois fichiers de configuration dans la VM, puis les placer dans un répertoire de travail.
Fenêtre de terminal # Depuis l'hôtesshpass -p 'nixos' scp -o StrictHostKeyChecking=no \~/lab-nixos/nixos-config/*.nix nixos@192.168.122.x:/tmp/nixos-config/N'oubliez pas de remplacer
"ssh-ed25519 AAAA... votre-cle-publique"dansconfiguration.nixpar le contenu réel de votre~/.ssh/id_ed25519.pub, sinon vous ne pourrez pas vous connecter au système installé. -
Verrouiller les dépendances en générant le
flake.lock.Fenêtre de terminal # Dans la VMcd /tmp/nixos-configsudo nix flake lockCette commande télécharge les index de nixpkgs et disko et fige leurs révisions exactes. C'est ce fichier, et lui seul, qui rend votre installation rejouable à l'identique dans six mois.
-
Partitionner et formater avec disko, qui prend en charge le partitionnement, le formatage et le montage en une seule commande.
Fenêtre de terminal sudo nix run github:nix-community/disko -- \--mode disko /tmp/nixos-config/disko-config.nixlsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT /dev/vda# NAME FSTYPE SIZE MOUNTPOINT# vda 20G# ├─vda1 vfat 512M /mnt/boot# └─vda2 ext4 19,5G /mntLes partitions montées sous
/mntsignalent que tout est prêt. -
Installer le système.
Fenêtre de terminal sudo mkdir -p /mnt/etc/nixossudo cp -r /tmp/nixos-config/* /mnt/etc/nixos/sudo nixos-install --flake /mnt/etc/nixos#nixos-lab --no-root-passwdL'installation télécharge le complément de la closure depuis le cache binaire, construit le système et installe le bootloader. Le message
installation finished!confirme le succès. Comptez une à deux minutes : l'essentiel de la closure est déjà sur l'ISO.--no-root-passwdest légitime ici, puisque la configuration n'autorise que l'accès SSH par clé. -
Redémarrer sur le disque en éjectant l'ISO.
Fenêtre de terminal virsh change-media nixos-lab sda --ejectvirsh reboot nixos-labSi la VM affiche un shell UEFI au lieu de démarrer, l'ordre de boot place encore le CD-ROM en premier :
virsh destroy nixos-lab, retirez l'entrée<boot dev="cdrom"/>avecvirsh edit, puisvirsh start nixos-lab.
Vérifier ce que vous avez obtenu
Section intitulée « Vérifier ce que vous avez obtenu »Connectez-vous par clé SSH, sans mot de passe, et validez le système. Voici les sorties réelles de la machine du lab.
ssh lab@192.168.122.x
nixos-version# 26.05.4659.8f0500b96605 (Yarara)
uname -r && hostname# 6.18.38# nixos-lab
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT /dev/vda# vda 20G# ├─vda1 vfat 512M /boot# └─vda2 ext4 19,5G /
du -sh /nix/store# 2.2G /nix/store
readlink -f /run/current-system# /nix/store/84137f6mhq4ygh3snwsz0xazw9z5qhhz-nixos-system-nixos-lab-26.05.4659.8f0500b96605
grep -E "^(PermitRootLogin|PasswordAuthentication)" /etc/ssh/sshd_config# PasswordAuthentication no# PermitRootLogin prohibit-passwordLe lien /run/current-system est le plus instructif : c'est la génération active, un simple pointeur vers une closure du store, et c'est cette commande qui dit quel système tourne réellement. La colonne Current de list-generations désigne, elle, la génération du profil : après un nixos-rebuild boot, elle affiche la nouvelle génération alors que le système en cours d'exécution est encore l'ancien. Ne confondez pas les deux.
Quant au durcissement SSH, vous n'avez édité aucun fichier dans /etc : ces lignes viennent de vos six lignes de configuration.nix, et elles seront régénérées à l'identique à chaque activation. C'est tout le modèle en une démonstration.
Casser, puis réparer
Section intitulée « Casser, puis réparer »Le lab n'a d'intérêt que si vous le cassez. Ajoutez nginx, avec un hôte virtuel (sans lui, le service tourne mais ne sert rien).
services.nginx = { enable = true; virtualHosts."localhost" = { root = "/var/www/html"; locations."/" = { index = "index.html"; }; }; };
systemd.tmpfiles.rules = [ "d /var/www/html 0755 root root -" "f /var/www/html/index.html 0644 root root - '<h1>Bonjour depuis NixOS</h1>'" ];Reconstruisez, puis observez le mécanisme complet.
cd /etc/nixossudo nixos-rebuild switch --flake .#nixos-lab
curl http://localhost# <h1>Bonjour depuis NixOS</h1>
nixos-rebuild list-generations# 1 ... 26.05.4659.8f0500b96605 6.18.38 False# 2 ... 26.05.4659.8f0500b96605 6.18.38 TrueDeux générations coexistent dans le store. Maintenant, annulez.
sudo nixos-rebuild switch --rollback# switching profile from version 2 to 1# stopping the following units: [...] nginx.service# removing user 'nginx'
systemctl status nginx.service# Unit nginx.service could not be found.Deux secondes. Le service, sa configuration et son utilisateur système ont disparu. Et souvenez-vous du piège de la limite 2 : votre configuration.nix contient toujours le bloc nginx. Le système et le fichier ont divergé, et c'est à vous de les remettre d'accord.
Ce que ce lab ne prouve pas
Section intitulée « Ce que ce lab ne prouve pas »Par honnêteté, et parce qu'un lab qui prétend tout démontrer ne démontre rien : le menu de systemd-boot n'a pas été vu à l'écran (il n'écrit pas sur la console série). Ce qui est prouvé, c'est le contenu de /boot/loader/entries/ (un fichier .conf par génération, distingués par leur ligne version) et le démarrage effectif sur une ancienne génération, obtenu avec bootctl set-oneshot suivi d'un redémarrage. L'affichage graphique du menu, lui, est décrit dans le guide de réparation.
Une variante de ce lab, avec un partitionnement manuel et une flake minimale sans disko, permet de voir exactement ce que disko fait à votre place.
Dépannage
Section intitulée « Dépannage »Les erreurs ci-dessous sont celles rencontrées en rejouant ce lab. La colonne « cause » compte plus que la solution : sur NixOS, les messages d'erreur pointent rarement vers le vrai coupable.
| Symptôme | Cause probable | Solution |
|---|---|---|
No space left on device alors que le disque est vide | La VM n'a que 4 Go de RAM : le tmpfs de l'ISO sature | Allouer 8 Go de RAM à la VM d'installation |
| ISO : « Access Denied » au démarrage | Secure Boot activé sur OVMF | OVMF_CODE_4M.fd avec loader.secure=no |
Permission denied sur l'ISO | Le shell de l'ISO est le compte nixos, pas root | Préfixer par sudo (sans mot de passe) |
To make it visible to Nix, run: git add ... | Un fichier du dépôt Git n'a jamais été indexé : la flake ne le voit pas | git add -A avant tout nixos-rebuild --flake |
| Boot : « waiting for device disk-main-root » | Modules virtio absents de l'initrd | Ajouter imports = [ qemu-guest.nix ] |
| Boot : shell UEFI au lieu du système | Le CD-ROM est encore premier dans l'ordre de boot | Éjecter l'ISO : virsh change-media nixos-lab sda --eject |
virsh send-key : des lettres manquent | Délai entre touches trop court | Passer à 0,3 seconde par touche |
nginx active mais rien sur le port 80 | Aucun hôte virtuel déclaré | Déclarer services.nginx.virtualHosts |
| Un binaire téléchargé ne s'exécute pas | Chargeur dynamique absent (stub-ld) | programs.nix-ld.enable et programs.nix-ld.libraries |
error: no profile version older than the current | Un nix-collect-garbage -d a supprimé les anciennes générations | Le rollback est perdu. Reconstruire depuis Git |
Une légende tenace mérite d'être corrigée : on lit partout qu'un dépôt Git est obligatoire pour installer par flake, sous peine d'une erreur d'assertion cryptique. Ce n'est plus vrai en 26.05. Un répertoire nu fonctionne, à condition que flake.lock existe déjà (le premier appel le crée, le second aboutit). Le vrai piège est plus sournois : dans un dépôt Git, tout fichier non indexé par git add est invisible pour la flake. Vous éditez un fichier, il n'a aucun effet, et vous cherchez vingt minutes. Nix a l'élégance de le dire :
To make it visible to Nix, run:git -C "/etc/nixos" add "flake.nix"Versionnez tout de même /etc/nixos : ce n'est pas une obligation technique, c'est ce qui verrouille le flake.lock dans l'historique, et c'est la moitié de la démonstration faite plus haut.
À retenir
Section intitulée « À retenir »- NixOS est un système entièrement déclaré : le fichier décrit l'état cible,
nixos-rebuildamène la machine à cet état. La dérive de configuration disparaît. - Le bénéfice réel n'est pas la reproductibilité bit-à-bit (les hashes portent sur les entrées), c'est la configuration reproductible plus le rollback atomique.
- « Si ça build, ça marche » est faux. Une erreur de nom d'option est attrapée avant tout ; une erreur de contenu passée en chaîne libre à un service passe le build, crée la génération et casse à l'activation. Le vrai filet, c'est le rollback.
- Le rollback a quatre limites : un seul cran, il ne corrige pas votre fichier de conf, un
nix-collect-garbage -dle détruit en laissant un menu de démarrage mensonger, et il ne restaure pas les données. Un rollback n'est pas une sauvegarde. - Git seul ne suffit pas. Avec les canaux, la révision de nixpkgs n'est pas dans le dépôt : le même commit rebâti plus tard donne un système différent. Avec une flake, le
flake.lockest versionné et redonne exactement le même chemin du store. - Aucun secret dans un fichier
.nix:/nix/storeest lisible par tous. Utilisez agenix ou sops-nix, dont le secret déchiffré atterrit dans un ramfs qui ne part jamais dans le swap. - Prévoyez la RAM et
/boot: l'évaluation coûte 606 Mo mesurés en configuration minimale, la marge est nulle sur 1 Go, etboot.loader.systemd-boot.configurationLimitn'est pas activé par défaut. - Pas de LTS, et un investissement qui se rentabilise sur une flotte : deux versions par an et sept mois de support, contre cinq ans chez Debian. Sur une machine unique, vous payez la complexité sans toucher le dividende.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »flake.nix, configuration.nix, disko-config.nix), puis lancez l'installation. Vous évaluez NixOS sans risque pour votre poste.