Nix Flakes - reproductibilité et multi-machines
Le problème sans flakes
Section intitulée « Le problème sans flakes »Avant les flakes, une config NixOS s’appuyait sur un canal (channel) pour résoudre nixpkgs. Le problème : deux machines avec le même configuration.nix peuvent avoir des résultats différents si leurs canaux pointent vers des commits différents. Pas d’erreur, pas d’avertissement - juste un comportement qui diverge silencieusement.
Les flakes règlent ça en rendant la source de chaque dépendance explicite et verrouillée dans un fichier git.
Inputs et outputs
Section intitulée « Inputs et outputs »Un flake c’est un flake.nix avec deux champs : inputs et outputs.
{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; };
outputs = { self, nixpkgs, ... }: { # ce qu'on expose };}inputs déclare les dépendances - d’autres flakes, des repos GitHub, des archives. outputs est une fonction qui reçoit ces inputs résolus et retourne ce qu’on veut exposer.
C’est là que le côté fonctionnel du langage Nix se voit le mieux. outputs est une fonction pure : mêmes inputs, mêmes outputs, sans effet de bord. Rien ne dépend de ce qui est installé sur la machine, rien n’est résolu depuis l’environnement local. Deux machines, même flake, même résultat.
flake.lock
Section intitulée « flake.lock »Au premier build, Nix crée un flake.lock qui fixe le commit exact de chaque input :
{ "nodes": { "nixpkgs": { "locked": { "rev": "a3ed7406349a9335cb4c2a71369b697cecd9d351", "type": "github", "owner": "NixOS", "repo": "nixpkgs" } } }}Ce fichier est à commiter. C’est lui qui garantit que deux machines qui font nixos-rebuild switch --flake . depuis le même commit git obtiennent exactement le même résultat.
Pour mettre à jour :
nix flake update # tous les inputsnix flake update nixpkgs # un input précisCe qu’on peut mettre dans outputs
Section intitulée « Ce qu’on peut mettre dans outputs »Configurations NixOS
Section intitulée « Configurations NixOS »L’usage principal pour une config perso. Chaque clé correspond à une machine :
outputs = { self, nixpkgs, ... }: { nixosConfigurations = { laptop = nixpkgs.lib.nixosSystem { modules = [ ./hosts/laptop ]; }; serveur = nixpkgs.lib.nixosSystem { modules = [ ./hosts/serveur ]; }; };};sudo nixos-rebuild switch --flake .#laptopEnvironnements de dev
Section intitulée « Environnements de dev »C’est honnêtement ce qui m’avait vendu les flakes avant même d’avoir une config NixOS. Rentrer dans le projet d’un inconnu qui a un flake.nix :
nix developCa télécharge exactement les dépendances déclarées dans un shell isolé. En sortant, rien ne reste installé globalement. Plus besoin de lire un README pour savoir quoi installer - si le projet a un flake, l’environnement est là.
devShells.x86_64-linux.default = pkgs.mkShell { packages = with pkgs; [ nodejs python3 postgresql ];};Packages buildables
Section intitulée « Packages buildables »Un flake peut aussi exposer des packages buildables :
nix build .#mon-packageLe résultat atterrit dans ./result, un lien symbolique vers le store. Je m’en sers par exemple pour builder une image Proxmox directement depuis le flake :
nix build .#proxmox-imageMon flake perso
Section intitulée « Mon flake perso »Ma config gère quatre machines depuis un seul flake : laptop, WSL, VM de test, serveur. Le WSL a des besoins différents des autres - il faut le module NixOS-WSL pour que l’intégration avec Windows fonctionne correctement. J’ai donc deux helpers distincts :
outputs = { self, nixpkgs, home-manager, nixos-wsl, ... }@inputs:let mkHost = host: nixpkgs.lib.nixosSystem { specialArgs = { inherit inputs; }; modules = [ ./hosts/${host} home-manager.nixosModules.home-manager { home-manager.users.tim = import ./home/tim; } ]; };
mkWsl = host: nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ nixos-wsl.nixosModules.wsl ./hosts/${host} home-manager.nixosModules.home-manager { home-manager.users.tim = import ./home/tim; } ]; };in { nixosConfigurations = { laptop = mkHost "laptop"; wsl = mkWsl "wsl"; };};Home Manager est branché directement dans le flake - pas géré séparément. La config utilisateur ./home/tim est la même sur toutes les machines : même shell, mêmes outils, peu importe où je me connecte. L’article suivant rentre dans le détail.
Commandes utiles
Section intitulée « Commandes utiles »# Voir ce qu'expose un flakenix flake show
# Vérifier la structure sans buildernix flake check
# Mettre à jour le lock filenix flake update
# Builder un outputnix build .#nom-du-package
# Entrer dans un devShellnix develop
# Appliquer une config NixOSsudo nixos-rebuild switch --flake .#nom-machine