Skip to main content

NixOS

NixOS est une distribution Linux basée sur Nix. C'est une distribution très spéciale qui a pour but de fournir un système d'exploitation fonctionnel, pur, et immutable, décrit par une configuration Nix. C'est aussi la distribution qui est utilisée sur les machines de l'école, car les fonctionnalités qu'elles proposent facilitent énormément sa gestion dans un tel environnement.

Dans cette partie, nous allons installer NixOS sur une machine virtuelle, et découvrir son fonctionnement ainsi que ses fonctionnalités principales.

Attention

Si vous voulez installer NixOS sur votre machine, vous pouvez le faire, mais c'est à vos risques et périls. Je vous conseille de le faire seulement si vous savez comment faire un dual boot, ou que quelqu'un est là pour vous aider.

Installation de NixOS

Mise en place de la machine virtuelle

Pour commencer, récupérez l'image ISO de NixOS depuis le site officiel en vous rendant sur cette page (descendez pour trouver les ISOs). Vous pouvez prendre la version graphique avec GNOME, c'est sur celle-ci que je vais m'appuyer.

Pour ce cours, j'utiliserai VirtualBox comme hyperviseur. Vous pouvez le télécharger sur cette page.

Après l'avoir installé (si ce n'était pas déjà fait), vous pouvez le lancer et créer une nouvelle machine virtuelle avec les spécifications suivantes :

  • Type : Linux
  • Version : Autre Linux (64-bit)
  • RAM : Au moins 2Go
  • Disque : Au moins 20Go
Attention

Si vous ne voyez que des options 32-bit, c'est que la virtualisation matérielle n'est pas activée dans votre BIOS.

Pour l'activer, cherchez dans votre BIOS une option dont le nom ressemble à "Virtualisation", "VT-x" ou "Intel Virtualisation Technology" (Intel) ou "AMD-V" ou "SVM" (AMD).

Une fois la machine virtuelle créée et avant de la démarrer, ouvrez les paramètres de la machine virtuelle et allez dans l'onglet "Système". Ici, dans le sous-onglet "Processeur", augmentez le nombre de processeurs alloués : mettez-en au moins 2, voire plus si vous avez des cœurs en rab.

Dans l'onglet "Stockage" ensuite, sélectionnez le lecteur de disque à gauche. Cliquez sur l'icône disque en haut à droite puis sur "Choose a disk file...", et sélectionnez l'image ISO que vous avez téléchargée précédemment.

Pour finir, dans l'onglet "Affichage", augmentez la mémoire vidéo au maximum.

Remarque

Vous êtes sur un écran à haut DPI ? Dans l'onglet Affichage, vous pouvez augmenter le facteur d'échelle, et ça même lorsque la machine virtuelle fonctionne.

Vous pouvez maintenant valider, et lancer la machine virtuelle.

Installation

Laissez le temps à l'installeur de démarrer, puis suivez simplement les instructions pour les premières étapes.

Lorsqu'il vous le demandera vous pouvez, si vous voulez, accepter l'installation de logiciels non-libres (unfree). Ça ne devrait pas avoir d'impact pour ce cours, mais dans le cas d'une véritable installation, c'est utile notamment pour installer les drivers NVIDIA ou Discord.

Arrivé à l'étape du partitionnement, vous pouvez choisir l'option Erase Disk. Évidemment, si vous êtes sur une vraie machine et que vous voulez faire un dual boot, vous devriez à la place faire un partitionnement manuel, sinon, laissez le reste des options par défaut et validez.

Lorsque ça sera terminé, ne redémarrez pas. Éteignez la machine virtuelle et ouvrez ses paramètres. Dans l'onglet "Stockage", retirez l'image ISO du lecteur de disque, vous pourrez ensuite la démarrer à nouveau.

Ce que fait l'installeur en détail

L'installeur de NixOS ne fait que trois choses :

  • Il partitionne votre disque
  • Il génère une configuration NixOS à partir de ce que vous avez sélectionné
  • Il lance la commande nixos-install pour installer le système à partir de cette configuration
  • C'est tout !

L'installation est plutôt rapide, c'est parce que l'installeur NixOS étant lui-même un système NixOS, il peut copier directement les dérivations déjà présentes sur son store vers le nouveau système.

Pour aller plus loin

Dans le cas d'une installation sans l'installeur graphique, il vous suffit de partitionner le disque comme vous le souhaitez, de générer une configuration NixOS à l'aide de la commande sudo nixos-generate-config --root /mnt, d'éditer /mnt/etc/nixos/configuration.nix comme vous voulez, puis de lancer l'installation avec la commande sudo nixos-install. Ensuite, plus qu'à redémarrer !

Si vous avez déjà une configuration NixOS de prête, cette méthode peut s'avérer plus facile.

La configuration du système

Rentrons dans le vif du sujet. Le principe de NixOS est de décrire son système dans un fichier de configuration Nix, et plus précisément dans le fichier /etc/nixos/configuration.nix.

Sur votre installation NixOS, ouvrez ce fichier dans l'éditeur de votre choix et analysons son contenu. Pour commencer, sa syntaxe générale :

/etc/nixos/conguration.nix (non formaté)
{ config, pkgs, ... }:

{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];

# Bootloader.
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.useOSProber = true;

# ...
}

Si vous avez bien suivi la partie sur le langage Nix, vous devriez saisir plusieurs choses :

  • Déjà, c'est une fonction.
  • Elle prend un set en paramètre et déstructure deux de ses attributs : config et pkgs, mais en accepte d'autres qu'elle ignore.
  • Elle retourne un aussi un set, contenant de multiples attributs dont des sous sets.

Déchiffrons maintenant plusieurs choses :

Les attributs donnés en paramètre

Un fichier de configuration NixOS (ou module NixOS, le nom officiel) reçoit plusieurs paramètres, dont entre autre :

  • config : un set contenant la configuration finale du système. Si l'on n'utilise pas tout simplement rec sur le set renvoyé, c'est parce que config est plus puissant : il permet de récupérer la valeur de n'importe quelle option, y compris celles que l'on a pas définies (on peut donc récupérer leur valeur par défaut) et celles définies dans d'autres fichiers (comme hardware-configuration.nix).
  • pkgs : l'instance de Nixpkgs, tout simplement. Plus précisément, cela correspond à l'instanciation du channel nixos de votre système.
  • options : un set contenant et permettant de définir les options disponibles dans tous les modules, nous verrons juste après ce que c'est.
  • modulesPath : Le chemin du dossier modules de Nixpkgs, contenant des modules optionnels inclus dans NixOS, permettant d'en importer certains. On reviendra sur ça juste après.

Les attributs renvoyés

Le set renvoyé par le module contient beaucoup d'attributs. Ces attributs sont des valeurs pour les options.

NixOS défini une liste d'options : des valeurs que l'on peut définir dans les modules de la configuration et qui ont un certain effet sur notre système.

Par exemple, cette partie de la configuration permet de définir le layout clavier de votre bureau (ici en AZERTY classique) :

/etc/nixos/conguration.nix (non formaté)
{ config, pkgs, ... }:

{
# ...

# Configure keymap in X11
services.xserver = {
layout = "fr";
xkbVariant = "";
};

# ...
}

NixOS dispose de beaucoup d'options, dont on peut parcourir la liste sur search.nixos.org. N'hésitez pas à parcourir un peu cette liste pour avoir un aperçu de tout ce que vous pouvez faire avec votre configuration NixOS.

Prenez aussi le temps de regarder celles qui sont définies dans votre fichier configuration.nix, des commentaires y sont attachés. Ignorez le formatage un peu étrange, ou le fait que certaines options soient définies via des sous ensembles (comme services.xserver dans l'exemple ci-dessus) et d'autres avec leur chemin complet (comme boot.loader.grub.device). C'est lié au fait que la config soit générée par un programme.

Rappel

N'oubliez pas que ces deux syntaxes sont équivalentes :

{ config, pkgs, ... }:

{
services.xserver.layout = "fr";
services.xserver.xkbVariant = "";
}
{ config, pkgs, ... }:

{
services.xserver = {
layout = "fr";
xkbVariant = "";
};
}

Les modules

La configuration Nix est donc décrite dans des modules. Un module NixOS est un fichier .nix de la forme suivante :

{ config, pkgs, ... }:

{
imports = [
# Chemins vers d'autres modules
];

options = {
# Création d'options
};

config = {
# Valeurs d'options
};
}

Dans la liste imports, vous pouvez ajouter des chemins vers d'autres modules. Ces derniers seront ajoutés à la liste des modules enregistrés. De votre côté, il devrait y avoir le module hardware-configuration.nix qui est généré par l'installeur NixOS. Il contient toute la partie de la configuration spécifique à votre matériel (notamment l'organisation de vos partitions).

Le set options permet de définir ses propres options. Par exemple, pour créer une option programe.sl.enable qui permet d'installer le programme sl, nous pouvons faire :

{ lib, ... }:

{
options = {
programs.sl.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to install the sl program.";
};
};
}

Dans le cas des options enable, nous pouvons même directement utiliser le raccourci lib.mkEnableOption :

{ lib, ... }:

{
options.programs.sl.enable = lib.mkEnableOption "sl";
}

Le set config est là où vous pouvez définir les valeurs d'options. Si vous n'avez pas défini l'attribut options, vous pouvez directement définir des valeurs dans le module au lieu de le faire dans config, c'est ce qu'il se passe dans configuration.nix et hardware-configuration.nix.

Pour reprendre notre exemple, nous pourrions y définir quoi faire lorsque notre option est activée. Il est alors tentant d'utiliser un if :

{ config, lib, pkgs, ... }:

{
options.programs.sl.enable = lib.mkEnableOption "sl";

config =
if config.programs.sl.enable then {
environment.systemPackages = [ pkgs.sl ];
} else { };
}

Mais en vérité, si vous faites ça, Nix plantera en indiquant une récursion infinie. Forcément ! config = if config... c'est pas très logique. La variable config est un agrégat des champs config de tous les modules enregistrés, y compris celui dans lequel on est en train d'écrire notre condition.

Pour remédier à ça, il faut utiliser la fonction mkIf :

{ config, lib, pkgs, ... }:

{
options.programs.sl.enable = lib.mkEnableOption "sl";

config = lib.mkIf config.programs.sl.enable {
environment.systemPackages = [ pkgs.sl ];
};
}

mkIf renvoie un set définissant une condition de façon déclarative. Le système de module de NixOS va ensuite s'occuper de l'utiliser au moment de l'évaluation des modules et de la construction de la configuration.

Mais quand plusieurs modules définissent la même option, comment NixOS sait quel module a la priorité ?

Il est possible de définir des priorités entre les valeurs d'options, notamment grâce à la fonction lib.mkOverride. Elle accepte une priorité numérique ainsi qu'une valeur, et le système de module choisira la valeur ayant la priorité la plus petite. Par exemple :

module-1.nix
{ lib, ... }:

{
programs.sl.enable = lib.mkOverride 2 true;
}
module-2.nix
{ lib, ... }:

{
programs.sl.enable = lib.mkOverride 1 false;
}

Si ces deux modules sont enregistrés, alors config.programs.sl.enable sera false car la valeur de module-2.nix a une priorité plus petite que celle de module-1.nix.

Mais pour éviter de se perdre avec les valeurs des priorités, il existe des fonctions appelant mkOverride avec une priorité prédéfinie, notamment :

  • lib.mkVMOverride : Priorité 10, utile notamment pour surcharger des valeurs dans le contexte d'une VM.
  • lib.mkForce : Priorité 50, utile pour surcharger la valeur de l'option.
  • lib.mkDefault : Priorité 1000, définit une valeur "par défaut", faite pour être surchargée si besoin.
  • lib.mkOptionDefault : Priorité 1500, automatiquement utilisé pour les valeurs default des options.
Info

Si vous précisez la valeur d'une option sans utiliser d'override, sa priorité sera considérée comme étant 100.

Pour plus d'informations sur les modules, notamment sur la création d'options, vous pouvez consulter la section du manuel de NixOS sur l'écriture de modules.

Pour aller plus loin

Les modules NixOS ne sont pas une fonctionnalité de Nix mais bien de NixOS/Nixpkgs, et sont entièrement implémentés dans Nixpkgs, notamment dans :

Bonus : Les modules de NixOS

NixOS inclut automatiquement des modules qui définissent toutes les options que vous pouvez utiliser. Mais en plus de ça, il existe des modules dans Nixpkgs qui ne sont pas inclus par défaut et qui permettent de définir la valeur d'un certain nombre d'options d'un coup.

Par exemple, si vous installez NixOS sur une machine sans écran (comme un serveur) vous pouvez activer le module headless qui va désactiver certains drivers graphiques, le splash de GRUB, et quelques fonctionnalités qui nécessitent usuellement une interaction (comme le mode emergency de systemd) :

{ modulesPath, ... }:

{
imports = [
"${modulesPath}/profiles/headless.nix"
];
}

Ce qui en vérité est simplement un raccourci (mais plus propre) pour :

{ ... }:

{
imports = [
<nixos/nixos/modules/profiles/headless.nix>
];
}
Remarque

Le nixos/nixos peut paraître étrange, mais c'est simplement le chemin vers le dossier nixos du channel nixos (et donc de Nixpkgs sur la branche nixos-(version qu'on a installée)).

On aurait aussi pu écrire nixpkgs/nixos, nixpkgs étant un alias vers nixos dans le NIX_PATH.

La commande nixos-rebuild

Maintenant que vous avez une configuration NixOS, voyons comment l'utiliser.

La commande nixos-rebuild est l'outil principal pour gérer sa configuration, c'est lui qui va vous permettre d'appliquer sur votre système les modifications de votre configuration. La commande dispose de plusieurs sous-commandes :

  • switch : Applique tout de suite la nouvelle configuration, sans redémarrer.
  • boot : Build la nouvelle configuration, mais l'applique seulement au prochain redémarrage.
  • test : Permet de tester la nouvelle configuration temporairement. Concrètement, la commande va faire la même chose que switch mais ses modifications disparaîtrons au prochain redémarrage.
  • dry-run : Permet de voir ce qui va être fait sans l'appliquer
  • build-vm : Créé une machine virtuelle avec la nouvelle configuration d'appliquée. La VM sera créée dans le dossier result du dossier courant et pourra être lancée avec result/bin/run-(hostname)-vm.
Remarque

Sans grande surprise, nixos-rebuild doit être lancé avec les droits root.

Attention

sudo nixos-rebuild switch est la manière la plus courante d'appliquer sa nouvelle configuration, mais la commande ne fait pas des miracles. Elle ne pourra pas appliquer des mises à jour de kernel, de drivers, etc. sans un redémarrage.

Il est rare, mais possible, qu'un switch fasse en partie planter des services. Quand c'est le cas, pas de panique, un redémarrage devrait régler le problème.

Pour aller plus loin

S'il n'est pas nécessaire de préciser à nixos-rebuild le chemin vers la configuration, c'est parce qu'il va chercher l'entrée nixos-config du NIX_PATH qui par défaut contient, entre autre, nixos-config=/etc/nixos/configuration.nix.

Vous pouvez indiquer à nixos-rebuild d'utiliser une autre configuration en changeant votre NIX_PATH ou via le paramètre -I permettant de le surcharger.

Les générations

L'un des plus gros points forts de NixOS est son système de génération.

En effet, tout comme pour nix-env, chaque configuration appliquée par nixos-rebuild génère une nouvelle génération de votre système. Cela signifie donc que vous pouvez revenir en arrière ! Pour ça, vous pouvez :

  • Ajouter le paramètre --rollback à nixos-rebuild pour qu'il se base sur la configuration de la génération précédente, permettant de facilement revenir en arrière.
  • Choisir une génération précédente dans le menu de votre bootloader. En effet, NixOS ajoute automatiquement une entrée dans votre bootloader pour chaque génération, permettant de choisir la configuration à utiliser au démarrage (la dernière étant sélectionnée par défaut).

Mais du coup, comment ça marche ?

Grâce à Nix, NixOS fait presque tout dans le store : tous vos programmes y sont, leurs fichiers de configuration, vos services, etc. De ce fait, il est possible d'y faire cohabiter plusieurs versions de votre système sans aucun souci, et ça sans duplication de données, conteneurs, ou machines virtuelles.

La différence entre les générations est donc uniquement dans les liens symboliques créés par Nix et NixOS.

En pratique, la génération active est liée dans le dossier /run/current-system. C'est un dossier très important qui contient, entre autre :

  • Votre kernel Linux ainsi que l'image initrd (initramfs) utilisée au démarrage (cette notion sera abordée en détail plus tard)
  • Le script d'initialisation du système init, premier programme lancé par le kernel après son démarrage
  • Tous les fichiers liés à systemd, le gestionnaire de services
  • Un dossier sw contenant l'environnement système de la génération, l'équivalent donc de ~/.nix-profile pour le système. On reviendra en détail dessus juste après.
  • Un script activate lancé au démarrage pour activer la génération, qui va :
    • Créer les dossiers nécessaires dans le système de fichier, avec les bonnes permissions
    • Mettre en place des liens symboliques un peu partout, notamment dans /etc
    • Mettre à jour la liste des groupes et des utilisateurs du système
    • etc.

Dans votre bootloader, NixOS créé une entrée pour chaque configuration en y inscrivant le chemin dans le store du Kernel, de l'initramfs, et du script init. Lorsque l'entrée est démarrée, init va mettre en place le strict minimum (notamment les permissions du store, et les dossiers de base) puis lancer activate, et pour finir, démarrer SystemD.

Pour voir à quoi ça ressemble en pratique, vous pouvez afficher le contenu du fichier de configuration de votre bootloader (si vous utilisez GRUB, ce qui est le cas par défaut, c'est /boot/grub/grub.cfg). Vous devriez voir plusieurs entrées avec pour chacune un chemin vers l'image du noyau linux dans le store, vers le script init, et vers l'initramfs.

Si vous avez plusieurs configurations, le script init de chacune d'entre elles devrait être situé dans le dossier d'une dérivation différente (celles de chacune des générations).

Comment supprimer les anciennes générations ?

nix-garbage-collect est votre ami. Il va supprimer toutes les générations exceptées la dernière. Si jamais vous voulez en garder certaines, il existe des paramètres pour spécifier lesquelles conserver, je vous invite à consulter le manuel de la commande.

Conseil

Il est possible de configurer NixOS pour lancer le garbage collector périodiquement via l'option nix.gc.

Le dossier /etc

Nix et NixOS essaient au maximum de dire à chaque programme de chercher ce dont ils ont besoin dans le store, mais malgré ça, il était trop difficile d'éviter l'existence du dossier /etc où est stockée la plupart des fichiers de configuration des programmes (et bien plus).

De ce fait, lors de l'application d'une configuration (ou au démarrage), le script activate va mettre en place tout un tas de liens dans le dossier /etc. Mais beaucoup de vrais fichiers y résident aussi, car ils ont besoin d'être modifiables (alors que, pour rappel, le store est immutable).

L'option environment.etc de NixOS permet de facilement définir des fichiers à l'intérieur.

L'environnement système

Comme mentionné plus haut, il existe sur NixOS un environnement système en plus de l'environnement de chaque utilisateur.

Cet environnement système est accessible via le dossier /run/current-system/sw (dont le dossier /bin devrait être dans le PATH automatiquement). Il constitue un environnement global pour le système, accessible par chaque utilisateur. Mais ces derniers peuvent surcharger cet environnement avec le leur, l'environnement de chaque utilisateur ayant la priorité sur celui du système.

La plupart des programmes y sont ajoutés implicitement par des options. Par exemple, l'option networking.networkmanager.enable que vous avez sûrement d'activée, va, entre autre évidemment, ajouter le programme networkmanager à l'environnement système.

Il est possible de directement ajouter des programmes à cet environnement en utilisant l'option environment.systemPackages (qui en pratique est utilisée par les autres options), permettant d'installer des paquets de façon déclarative.

En revanche, passer par cette option fait que le paquet sera installé pour tous les utilisateurs, et il peut être plus propre de l'installer seulement pour soi. Pour ça, vous pouvez passer par :

  • nix-env
  • l'option users.users.(votre utilisateur).packages
  • Home manager, un outil permettant d'avoir l'équivalent d'une configuration NixOS mais pour un utilisateur. Si vous considérez utiliser NixOS sur votre véritable machine, je vous recommande très fortement de l'utiliser.

Je vous recommande très fortement de gérer vos paquets de façon déclarative (surtout par Home manager) et de garder nix-env pour des paquets un peu plus "temporaires", ça vous facilitera grandement la gestion de votre système.

Le système de fichier

Du fait de son fonctionnement, le système de fichier de NixOS est très particulier.

Pas de dossier /bin, /usr, ou /lib, à l'exception de /bin/sh et /usr/bin/env qui sont nécessaires au fonctionnement de beaucoup trop de choses. De ce fait, beaucoup de programmes ne peuvent pas être utilisés sans les patcher.

Rien qu'un script bash commençant par #!/bin/bash ne fonctionnera pas, il faudra le remplacer par #!/usr/bin/env bash.

De plus, les binaires dynamiques pré-compilés ne fonctionneront pas non plus, car il est écrit à l'intérieur de trouver /lib64/ld-linux-x86-64.so.2, qui lui ira chercher des bibliothèques dans /lib64, qui n'existe pas.

Ce sont les plus gros inconvénients de NixOS, et il peut être assez difficile de les résoudre. Il existe cependant plusieurs méthodes pour le faire :

  • patchelf : NixOS fournit un programme appelé patchelf qui permet de patcher certaines informations d'un binaire, notamment le chemin vers l'interpréteur (comme /lib64/ld-linux-x86-64.so.2), et le chemin vers les bibliothèques partagées.
  • Faire une dérivation : Si c'est possible, empaqueter un programme dans une dérivation peut être une solution facile pour le rendre utilisable sur NixOS :
    • Soit en ajoutant autoPatchelfHook aux nativeBuildInputs ainsi que les dépendances du programme dans buildInputs, Nix se chargera alors d'automatiquement patcher tous les binaires et bibliothèques qu'il trouvera. Par défaut, Nix change aussi tous les shebang (comme #!/bin/bash) des scripts qu'il trouve.
    • Soit en utilisant buildFHSUserEnv pour créer un système de fichier classique complet avec /bin, /usr, /lib, etc. et les paquets souhaités à l'intérieur, si le programme a besoin d'un environnement complet. Nix lancera automatiquement le programme à l'intérieur. C'est la méthode utilisée notamment pour Steam.

Il existe aussi des programmes tierces permettant de faire ce travail pour vous, par exemple :

  • nix-ld : un interpréteur alternatif qui va automatiquement chercher le nécessaire dans des variables d'environnement (que vous devez quand même définir, par exemple via un shell).
  • nix-alien : la solution la plus simple, permettant de directement lancer un binaire pré-compilé via plusieurs moyens. Soit en créant automatiquement un FHS et en le lançant à l'intérieur, soit en créant automatiquement un shell avec les bonnes variables d'environnement pour nix-ld. Il est aussi capable de vous lister les librairies nécessaires pour lancer un binaire.

Certains des cas les plus complexes sont les programmes qui téléchargent des binaires pré-compilés, comme Steam ou VS Code (lorsqu'il télécharge des plugins contenant des binaires). Dans ce genre de cas, buildFHSUserEnv est la seule solution, c'est pour ça qu'ils ont été implémentés avec dans Nixpkgs.

Dans certains cas, il existe des versions avec et sans FHS dans les dépôts, par exemple il existe à la fois vscode et vscode-fhs. Si vous avez des problèmes avec des extensions, il faut alors privilégier vscode-fhs.

Bonus : Mettre à jour son système

Pour mettre à jour son système, comme pour Nix, il suffit de mettre à jour ses channels puis de lancer nixos-rebuild. Faites simplement attention à mettre à jour vos channels système (en utilisant sudo), sur lesquels se base nixos-rebuild. Pour aller plus vite, il existe un paramètre --upgrade sur nixos-rebuild qui va automatiquement lancer sudo nix-channel --update pour vous avant.

Vers une nouvelle version de NixOS

Lorsqu'une nouvelle version de NixOS sort et que vous voulez passer dessus, commencez d'abord par lire la section du manuel relative à cette version. Vous y retrouverez les changements importants, et les problèmes potentiels que vous pourriez rencontrer lors d'une mise à jour.

Ensuite, changez simplement votre channel nixos par le nouveau, par exemple pour passer à la version 23.05 :

sudo nix-channel --add https://nixos.org/channels/nixos-23.05 nixos

Mettez ensuite à jour vos channels, puis lancez nixos-rebuild. Si vous avez installé des paquets avec nix-env, vous pouvez aussi les mettre à jour avec le paramètre -u.

Le stateVersion

Si vous avez parcouru votre configuration.nix, vous avez peut-être remarqué l'existence de l'option system.stateVersion.

À première vue, vous pensez peut-être qu'elle correspond à la version de NixOS que vous avez, et vous aurez envie de la changer lorsque vous changerez de version de NixOS. Ne faites surtout pas ça !

Comme l'indique l'énorme commentaire qui l'accompagne, cette option ne sert pas du tout à ça, mais à préciser la version de NixOS que vous aviez au moment de son l'installation.

Beaucoup de programmes écrivent des fichiers dans /etc ou /var. Par exemple si vous installez PostgreSQL, il va créer un dossier /var/lib/postgresql/data contenant notamment le contenu des bases de données. Mais imaginez que vous mettiez à jour NixOS, que PostgreSQL change de version majeur, et que le format de ses fichiers change. La mise à jour pourrait alors casser vos bases de données !

C'est là que le stateVersion intervient. Quand NixOS va voir que la version que vous avez initialement installée proposait l'ancienne version de PostgreSQL, il va savoir qu'il faut faire une migration de vos bases de données, et il va donc éviter que tout se casse. C'est pareil pour beaucoup d'autres choses !

Le stateVersion est donc très important, et c'est dans sa nature de ne pas changer. Évidemment, si vous transférez votre configuration sur une autre machine ou que vous réinstallez NixOS en perdant notamment votre /var, là, il faut le faire. Il arrive aussi très rarement que les notes de versions indiquent de le mettre à jour, alors pensez à les regarder !

Conclusion

Quoi ? C'est tout ?

Et oui, NixOS lui-même n'est pas si gros que ça, le principal résidant dans l'existence de la configuration système et le reste étant simplement apporté par Nix. Mais ces deux choses suffisent à faire de NixOS est un système d'exploitation unique en son genre.

Grâce au système de génération, tant que vous ne cassez pas votre bootloader et ne supprimez pas toutes vos anciennes générations, il devrait être impossible de casser votre système.

Vous pouvez donc profiter d'une très grande stabilité tout en profitant de paquets à jour et que vous pouvez customiser jusqu'au flag de compilation. D'une certaine manière, NixOS rassemble ainsi les avantages de Debian, Arch Linux, et Gentoo, mais sans la plupart de leurs inconvénients (même si, ne soyons pas aveugles, il en ajoute quelques nouveaux et pas forcément des moindres).

Son système de configuration déclarative est très puissant, et est la principale raison pour laquelle il a été choisi pour les salles machines d'EPITA, simplifiant énormément leur gestion par rapport au mélange d'outils tiers et de script bash permettant la gestion d'Arch Linux il y a quelques années.

En plus des ressources déjà citées pour Nix, n'hésitez pas à parcourir le manuel de NixOS.