Les flakes sont le mécanisme de reproductibilité native de Nix. Un fichier flake.nix déclare des dépendances versionnées (les inputs), et flake.lock verrouille leurs révisions exactes. Résultat : chaque membre de l’équipe, chaque serveur CI et chaque machine de production obtient exactement le même environnement. Ce guide couvre la structure complète d’un flake, les commandes de gestion, et la migration depuis shell.nix.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer un flake avec
nix flake initet comprendre sa structure - Déclarer des inputs (nixpkgs, flake-utils) et les verrouiller avec
flake.lock - Définir des outputs : devShells, packages, apps
- Construire, exécuter et inspecter un flake
- Convertir un projet
shell.nixclassique vers les flakes - Supporter plusieurs architectures avec
flake-utils
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Les channels Nix classiques (guide précédent) posent un problème fondamental : chaque machine peut pointer vers une révision différente de nixpkgs. Même avec fetchTarball et un hash, le pinning reste manuel et fragile.
Les flakes résolvent ce problème en pratique quotidienne :
- Votre collègue clone votre dépôt et obtient les mêmes versions de Python, Node.js et tous les outils — automatiquement
- La CI construit avec les mêmes dépendances que votre poste — sans configuration supplémentaire
- Vous mettez à jour nixpkgs d’un seul
nix flake update, avec un diff vérifiable dansflake.lock - Vous composez plusieurs sources (nixpkgs stable, un overlay privé, un outil depuis GitHub) dans un seul fichier déclaratif
Activer les flakes dans votre configuration Nix
Section intitulée « Activer les flakes dans votre configuration Nix »Les flakes sont une fonctionnalité expérimentale qu’il faut activer explicitement. Si vous avez suivi le guide d’installation, c’est déjà fait.
Vérifiez votre configuration :
grep experimental-features ~/.config/nix/nix.conf 2>/dev/null || \grep experimental-features /etc/nix/nix.conf 2>/dev/nullexperimental-features = nix-command flakesSi la ligne est absente :
mkdir -p ~/.config/nixecho "experimental-features = nix-command flakes" >> ~/.config/nix/nix.confInitialiser un flake avec nix flake init
Section intitulée « Initialiser un flake avec nix flake init »La commande nix flake init génère un flake.nix de base dans le répertoire courant. Le répertoire doit être un dépôt Git — les flakes ne fonctionnent qu’avec des fichiers suivis par Git.
-
Créez un répertoire et initialisez Git :
Fenêtre de terminal mkdir mon-projet && cd mon-projetgit init -
Générez le flake de base :
Fenêtre de terminal nix flake initwrote: "/home/lab/mon-projet/flake.nix" -
Examinez le fichier généré :
Fenêtre de terminal cat flake.nix{description = "A very basic flake";inputs = {nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";};outputs = { self, nixpkgs }: {packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;packages.x86_64-linux.default = self.packages.x86_64-linux.hello;};} -
Ajoutez le fichier à Git (obligatoire pour que Nix le voie) :
Fenêtre de terminal git add flake.nix
Anatomie du fichier flake.nix
Section intitulée « Anatomie du fichier flake.nix »Un flake.nix est une expression Nix qui retourne un attribute set avec trois clés :
{ description = "Description du projet"; # texte libre
inputs = { # Les dépendances et leur source };
outputs = { self, ... }: # Ce que le flake produit { };}| Clé | Rôle | Obligatoire |
|---|---|---|
description | Texte affiché par nix flake metadata | Non (recommandé) |
inputs | Dépendances externes avec leur URL | Oui |
outputs | Fonction qui retourne packages, shells, apps… | Oui |
La clé outputs est une fonction dont le premier argument est toujours self (le flake lui-même), suivi d’un argument par input déclaré.
Déclarer ses dépendances dans inputs
Section intitulée « Déclarer ses dépendances dans inputs »Les inputs déclarent les sources dont votre flake dépend. La plus courante est nixpkgs.
Types de sources
Section intitulée « Types de sources »inputs = { # Branche spécifique nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
# Branche stable nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11";
# Un outil tiers flake-utils.url = "github:numtide/flake-utils";};Format : github:propriétaire/dépôt/branche
inputs = { mon-outil.url = "git+https://gitlab.example.com/equipe/outil.git?ref=main";};Format : git+URL?ref=branche
inputs = { mon-lib.url = "path:./lib";};Utile pour un monorepo contenant plusieurs flakes.
inputs = { source.url = "https://example.com/archive.tar.gz"; source.flake = false;};flake = false indique que la source n’est pas elle-même un flake.
Partager un même nixpkgs entre inputs avec follows
Section intitulée « Partager un même nixpkgs entre inputs avec follows »Quand un input (comme flake-utils) dépend lui-même de nixpkgs, vous pouvez forcer l’utilisation de votre version :
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils";
# Force flake-utils à utiliser notre nixpkgs flake-utils.inputs.systems.follows = "systems"; systems.url = "github:nix-systems/x86_64-linux";};Sans follows, chaque input télécharge sa propre copie de ses dépendances. Avec follows, vous déduplicez et garantissez la cohérence.
Le fichier flake.lock : reproductibilité garantie
Section intitulée « Le fichier flake.lock : reproductibilité garantie »La première évaluation d’un flake génère automatiquement un flake.lock. Ce fichier JSON enregistre la révision exacte de chaque input :
{ "nodes": { "nixpkgs": { "locked": { "lastModified": 1775710090, "narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=", "owner": "nixos", "repo": "nixpkgs", "rev": "4c1018dae018162ec878d42fec712642d214fdfa", "type": "github" }, "original": { "owner": "nixos", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { "nixpkgs": "nixpkgs" } } }, "root": "root", "version": 7}Trois informations clés :
rev: le commit exact de nixpkgs utilisénarHash: le hash cryptographique du contenu — garantit l’intégritéoriginal: la source telle que déclarée dansinputs
Définir ses outputs : devShells, packages, apps
Section intitulée « Définir ses outputs : devShells, packages, apps »La fonction outputs retourne un attribute set dont les clés suivent une convention standardisée. Voici un flake complet avec les trois outputs les plus courants :
{ description = "Projet Python avec devShell et package";
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; };
outputs = { self, nixpkgs }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; python = pkgs.python312; in { # Environnement de développement devShells.${system}.default = pkgs.mkShell { packages = [ (python.withPackages (ps: [ ps.requests ps.pytest ])) pkgs.curl pkgs.jq ]; shellHook = '' echo "Environnement Python pret" export PROJECT_NAME=mon-projet ''; };
# Paquet construisible packages.${system}.default = pkgs.writeShellScriptBin "hello-projet" '' echo "Bienvenue dans mon-projet !" '';
# Application exécutable apps.${system}.default = { type = "app"; program = "${self.packages.${system}.default}/bin/hello-projet"; }; };}Les types d’outputs standards
Section intitulée « Les types d’outputs standards »| Output | Commande associée | Rôle |
|---|---|---|
devShells.<system>.default | nix develop | Environnement de développement |
packages.<system>.default | nix build | Paquet à construire |
apps.<system>.default | nix run | Application à exécuter |
overlays.default | — | Modification de nixpkgs |
nixosConfigurations.<nom> | nixos-rebuild | Configuration NixOS complète |
nixosModules.default | — | Module NixOS réutilisable |
Construire, exécuter et inspecter un flake
Section intitulée « Construire, exécuter et inspecter un flake »Visualiser la structure avec nix flake show
Section intitulée « Visualiser la structure avec nix flake show »nix flake showgit+file:///home/lab/demo-flake-devshell├───apps│ └───x86_64-linux│ └───default: app├───devShells│ └───x86_64-linux│ └───default: development environment 'nix-shell'└───packages └───x86_64-linux └───default: package 'hello-projet'Consulter les métadonnées avec nix flake metadata
Section intitulée « Consulter les métadonnées avec nix flake metadata »nix flake metadataResolved URL: git+file:///home/lab/demo-flake-devshellDescription: Projet Python avec devShell et packagePath: /nix/store/d9pvgm44r0dnqlg8whgdpzd7q73ihayj-sourceInputs:└───nixpkgs: github:nixos/nixpkgs/4c1018dae018162ec878d42fec712642d214fdfa (2026-04-09)Entrer dans l’environnement de développement
Section intitulée « Entrer dans l’environnement de développement »nix developEnvironnement Python pretLe shellHook s’exécute et toutes les dépendances sont disponibles :
python3 --version && echo $PROJECT_NAMEPython 3.12.13mon-projetConstruire un paquet
Section intitulée « Construire un paquet »nix buildbuilding '/nix/store/8s05glip2sx5zb5gj1n6l0r2ggjn7h96-hello-projet.drv'...Le résultat est un lien symbolique ./result pointant vers le store :
ls -la resultresult -> /nix/store/10s5j3mfdg22k1597x580qrhprnzcjwb-hello-projet./result/bin/hello-projetBienvenue dans mon-projet !Exécuter directement avec nix run
Section intitulée « Exécuter directement avec nix run »nix runBienvenue dans mon-projet !nix run combine nix build + exécution du binaire par défaut en une seule commande.
Vérifier la validité du flake
Section intitulée « Vérifier la validité du flake »nix flake checkchecking flake output 'devShells'...checking derivation devShells.x86_64-linux.default...checking flake output 'packages'...checking derivation packages.x86_64-linux.default...checking flake output 'apps'...checking app 'apps.x86_64-linux.default'...all checks passed!nix flake check évalue toutes les dérivations et vérifie la conformité des outputs. Indispensable dans une pipeline CI.
Mettre à jour les dépendances
Section intitulée « Mettre à jour les dépendances »Pour mettre à jour tous les inputs :
nix flake updatePour mettre à jour un seul input :
nix flake update nixpkgsAprès la mise à jour, vérifiez le diff de flake.lock avec git diff flake.lock avant de commiter.
Convertir un projet shell.nix existant vers les flakes
Section intitulée « Convertir un projet shell.nix existant vers les flakes »Si vous avez un shell.nix classique qui utilise <nixpkgs>, voici comment le migrer vers un flake.
Avant : shell.nix classique
Section intitulée « Avant : shell.nix classique »{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { packages = with pkgs; [ python312 python312Packages.requests git curl ];
shellHook = '' echo "Environnement dev classique" '';}Ce fichier fonctionne avec nix-shell, mais les versions dépendent du channel actif sur chaque machine.
Après : flake.nix
Section intitulée « Après : flake.nix »{ description = "Projet migre de shell.nix vers flake";
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; };
outputs = { self, nixpkgs }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; in { devShells.${system}.default = pkgs.mkShell { packages = with pkgs; [ python312 python312Packages.requests git curl ];
shellHook = '' echo "Environnement dev (flake, nixos-24.11)" ''; }; };}Les différences concrètes
Section intitulée « Les différences concrètes »| Aspect | shell.nix | flake.nix |
|---|---|---|
| Source nixpkgs | <nixpkgs> (channel local) | github:nixos/nixpkgs/nixos-24.11 (verrouillé) |
| Versions obtenues | Varient selon la machine | Identiques partout |
| Commande d’entrée | nix-shell | nix develop |
| Verrouillage | Aucun (ou fetchTarball manuel) | Automatique (flake.lock) |
Le résultat avec nixos-24.11 verrouillé :
nix develop --command bash -c "python3 --version && git --version"Python 3.12.8git version 2.47.2Tandis qu’avec nixos-unstable, les mêmes paquets donnent Python 3.12.13 et git 2.53.0.
Supporter plusieurs architectures
Section intitulée « Supporter plusieurs architectures »Par défaut, un flake cible un seul system (typiquement "x86_64-linux"). Pour supporter Linux et macOS sur x86_64 et ARM, utilisez flake-utils :
Avec flake-utils
Section intitulée « Avec flake-utils »{ description = "Flake multi-architecture";
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; };
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; in { devShells.default = pkgs.mkShell { packages = [ pkgs.jq pkgs.curl ]; };
packages.default = pkgs.hello; } );}eachDefaultSystem itère automatiquement sur les quatre systèmes standards :
nix flake show├───devShells│ ├───aarch64-darwin│ │ └───default omitted (use '--all-systems' to show)│ ├───aarch64-linux│ │ └───default omitted (use '--all-systems' to show)│ ├───x86_64-darwin│ │ └───default omitted (use '--all-systems' to show)│ └───x86_64-linux│ └───default: development environment 'nix-shell'└───packages ├───aarch64-darwin │ └───default omitted (use '--all-systems' to show) ├───aarch64-linux │ └───default omitted (use '--all-systems' to show) ├───x86_64-darwin │ └───default omitted (use '--all-systems' to show) └───x86_64-linux └───default: package 'hello-2.12.3'Sans flake-utils
Section intitulée « Sans flake-utils »Si vous préférez éviter la dépendance à flake-utils, utilisez genAttrs de nixpkgs :
outputs = { self, nixpkgs }: let supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs supportedSystems; pkgsFor = system: nixpkgs.legacyPackages.${system}; in { packages = forAllSystems (system: { default = (pkgsFor system).hello; });
devShells = forAllSystems (system: { default = (pkgsFor system).mkShell { packages = [ (pkgsFor system).hello ]; }; }); };Intégrer les flakes avec direnv
Section intitulée « Intégrer les flakes avec direnv »direnv active automatiquement l’environnement du flake quand vous entrez dans le répertoire du projet. Plus besoin de taper nix develop manuellement.
-
Installez direnv et nix-direnv :
Fenêtre de terminal nix profile install nixpkgs#direnv nixpkgs#nix-direnv -
Configurez votre shell (ajoutez à
~/.bashrcou~/.zshrc) :Fenêtre de terminal eval "$(direnv hook bash)" # ou hook zshsource $HOME/.nix-profile/share/nix-direnv/direnvrc -
Créez un fichier
.envrcà la racine du projet :Fenêtre de terminal echo "use flake" > .envrcdirenv allow -
À chaque
cddans le projet, l’environnement se charge automatiquement.
Structure recommandée d’un projet avec flakes
Section intitulée « Structure recommandée d’un projet avec flakes »Pour un projet réel, organisez vos fichiers Nix dans un sous-répertoire :
Répertoiremon-projet/
- flake.nix Point d’entrée principal
- flake.lock Versions verrouillées (généré)
- .envrc Pour direnv (
use flake) Répertoirenix/
Répertoiredevshells/
- default.nix Définition du devShell
Répertoirepackages/
- default.nix Définitions de paquets
Répertoireoverlays/
- default.nix Overlays personnalisés
Répertoiresrc/ Code source de l’application
- …
Le flake.nix importe ensuite ces fichiers :
{ description = "Projet organisé";
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; in { devShells.${system}.default = import ./nix/devshells/default.nix { inherit pkgs; }; packages.${system}.default = import ./nix/packages/default.nix { inherit pkgs; }; };}Comparaison flakes et channels
Section intitulée « Comparaison flakes et channels »| Aspect | Channels (classique) | Flakes |
|---|---|---|
| Verrouillage | Manuel (fetchTarball + hash) | Automatique (flake.lock) |
| Reproductibilité | Difficile à garantir | Garantie par défaut |
| Structure | Libre (convention par projet) | Standardisée (inputs/outputs) |
| Composition | Complexe (imports manuels) | Native (follows, multi-inputs) |
| Évaluation | Impure (accès au système de fichiers) | Pure (hermétique) |
| Commandes | nix-env, nix-shell, nix-build | nix develop, nix build, nix run |
| Mise à jour | nix-channel --update (global) | nix flake update (par projet) |
| CI/CD | Configuration manuelle | Structure prédictible |
Dépannage courant
Section intitulée « Dépannage courant »| Symptôme | Cause probable | Solution |
|---|---|---|
error: experimental feature 'flakes' is disabled | Flakes non activés | Ajouter experimental-features = nix-command flakes dans ~/.config/nix/nix.conf |
error: getting status of '/flake.nix': No such file or directory | Fichier non suivi par Git | git add flake.nix |
error: path '/nix/store/…' is not valid | Fichier manquant dans Git | git add <fichier-manquant> |
warning: Git tree '…' is dirty | Modifications non commitées | git add -A && git commit (ou ignorer l’avertissement) |
| Build échoue en CI mais pas en local | flake.lock absent ou pas à jour | git add flake.lock && git commit |
--update-input affiche un warning | Syntaxe dépréciée | Utiliser nix flake update <input> |
À retenir
Section intitulée « À retenir »- Un flake =
flake.nix(déclaration) +flake.lock(verrouillage) dans un dépôt Git - Les inputs déclarent les sources ;
followsévite la duplication - Les outputs produisent des devShells, packages, apps — avec une convention standardisée
nix developremplacenix-shell,nix buildremplacenix-build,nix runexécute directementnix flake checkvalide la structure — indispensable en CInix flake updatemet à jour les inputs ; le diff deflake.locksert de revue- flake-utils simplifie le support multi-architecture
- direnv + nix-direnv activent l’environnement automatiquement