Un fichier shell.nix à la racine de votre projet, un nix-shell (ou
nix develop), et tout votre outillage est là — même version, même
configuration, pour tous les membres de l’équipe. Pas de README à
re-lire, pas de conflits de versions, pas de “ça marche sur ma machine”.
Ce guide vous montre comment construire ces environnements pour Python,
Node.js, Rust et des projets mixtes.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre le rôle de
mkShellet la structure d’unshell.nix - Créer un environnement Python avec bibliothèques via
withPackages - Créer un environnement Node.js et un environnement Rust
- Passer des variables d’environnement et un shellHook au shell
- Utiliser
nix developavec un flake comme alternative moderne - Charger l’environnement automatiquement avec direnv
- Comparer
nix-shell/nix developavec venv, nvm et Docker
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Chaque projet a ses dépendances : une version de Python, des bibliothèques, des outils CLI, une version de Node.js… Au quotidien, vous rencontrez ces situations :
- un nouveau développeur rejoint le projet et passe une demi-journée à installer les bons outils,
- deux projets exigent des versions différentes de Node.js ou Python,
- un script CI échoue parce que la version de
jqdiffère du poste local, - le
READMEdit “installer gcc, cmake, libssl-dev, python3.12…” mais personne ne le maintient à jour.
Avec Nix, un seul fichier (shell.nix ou flake.nix) décrit
l’environnement de manière reproductible. Il est versionné avec le code et
garantit que tout le monde travaille avec le même outillage.
mkShell : la brique fondamentale
Section intitulée « mkShell : la brique fondamentale »pkgs.mkShell est une fonction qui crée un environnement de développement.
Elle attend un attrset avec :
| Attribut | Rôle |
|---|---|
packages | Liste des paquets disponibles dans le shell |
shellHook | Script exécuté à l’entrée dans le shell |
name | Nom affiché (optionnel) |
| toute autre clé | Devient une variable d’environnement |
Premier shell.nix minimal
Section intitulée « Premier shell.nix minimal »{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { packages = with pkgs; [ python312 git vim ];}Pour entrer dans l’environnement :
nix-shellPython 3.12.13git version 2.53.0Quand vous tapez exit, les outils disparaissent — ils ne sont
accessibles que dans le shell Nix.
Environnement Python avec bibliothèques
Section intitulée « Environnement Python avec bibliothèques »Python “nu” ne suffit pas : vous avez besoin de requests, flask,
pytest… La fonction withPackages crée un Python qui inclut les
bibliothèques demandées.
{ pkgs ? import <nixpkgs> {} }:
let pythonEnv = pkgs.python312.withPackages (ps: [ ps.requests ps.flask ps.pytest ]);inpkgs.mkShell { packages = with pkgs; [ pythonEnv git ripgrep ];
PROJECT_NAME = "demo-api"; FLASK_DEBUG = "1";
shellHook = '' echo "==================================" echo " Projet: $PROJECT_NAME" echo " Python: $(python3 --version 2>&1)" echo " Flask debug: $FLASK_DEBUG" echo "==================================" '';}nix-shell================================== Projet: demo-api Python: Python 3.12.13 Flask debug: 1==================================Vérifions que les bibliothèques sont bien disponibles :
python3 -c "import requests; print(f'requests {requests.__version__}')"python3 -c "import pytest; print(f'pytest {pytest.__version__}')"requests 2.32.5pytest 9.0.2Les bibliothèques sont installées dans le store Nix, pas dans un venv
classique. Elles disparaissent quand vous quittez le shell.
Comprendre withPackages
Section intitulée « Comprendre withPackages »withPackages attend une fonction qui reçoit l’ensemble des paquets
Python disponibles (ps) et retourne la liste de ceux que vous voulez :
pkgs.python312.withPackages (ps: [ ps.requests # ← sélectionne requests dans l'ensemble Python ps.flask # ← sélectionne flask])La syntaxe ps: [ ... ] est une fonction anonyme (lambda) — un concept
couvert dans le guide du langage Nix.
Trouver les noms de paquets Python
Section intitulée « Trouver les noms de paquets Python »Tous les paquets Python nixpkgs sont listés avec le préfixe python3Packages. :
nix search nixpkgs python3Packages.requestsDans un shell.nix, on utilise ps.requests (raccourci fourni par
withPackages).
Environnement Node.js
Section intitulée « Environnement Node.js »{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { packages = with pkgs; [ nodejs_22 jq curl ];
shellHook = "echo 'Node.js:' $(node --version)";}nix-shell --run "node --version && jq --version"v22.22.2jq-1.8.1Environnement Rust
Section intitulée « Environnement Rust »{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { packages = with pkgs; [ rustc cargo gcc ];
RUST_BACKTRACE = "1";
shellHook = "echo 'Rust:' $(rustc --version)";}nix-shell --run "rustc --version && cargo --version"rustc 1.94.0 (4a4ef493e 2026-03-02)cargo 1.94.0 (85eff7c80 2026-01-15)La variable RUST_BACKTRACE = "1" est automatiquement exportée — toute
clé inconnue de mkShell devient une variable d’environnement.
Variables d’environnement et shellHook
Section intitulée « Variables d’environnement et shellHook »Variables d’environnement
Section intitulée « Variables d’environnement »Ajoutez simplement des clés à l’attrset de mkShell :
pkgs.mkShell { packages = [ ... ];
# Deviennent des variables d'environnement PROJECT_NAME = "mon-api"; FLASK_DEBUG = "1"; FLASK_RUN_PORT = "5000"; DATABASE_URL = "postgresql://localhost:5432/dev";}nix-shell --run "echo \$PROJECT_NAME \$FLASK_RUN_PORT"mon-api 5000shellHook : script d’initialisation
Section intitulée « shellHook : script d’initialisation »Le shellHook s’exécute à chaque entrée dans le shell. Il sert à :
- afficher un message de bienvenue,
- activer un environnement,
- vérifier des prérequis,
- créer des fichiers temporaires.
shellHook = '' echo "==================================" echo " Projet: $PROJECT_NAME" echo " Python: $(python3 --version 2>&1)" echo "=================================="'';nix develop : l’alternative moderne avec les flakes
Section intitulée « nix develop : l’alternative moderne avec les flakes »nix develop est l’équivalent de nix-shell dans le monde des flakes.
Il nécessite un fichier flake.nix (et un dépôt Git).
{ description = "Environnement de développement Node.js";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; };
outputs = { self, nixpkgs }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; in { devShells.${system}.default = pkgs.mkShell { packages = with pkgs; [ nodejs_22 jq curl ];
shellHook = "echo 'Node.js:' $(node --version)"; }; };}-
Initialisez le dépôt (les flakes exigent Git) :
Fenêtre de terminal git init && git add flake.nix -
Entrez dans l’environnement :
Fenêtre de terminal nix developRésultat Node.js: v22.22.2 -
Vérifiez le
flake.lockgénéré :Fenêtre de terminal cat flake.lock | head -10Extrait de flake.lock {"nodes": {"nixpkgs": {"locked": {"lastModified": 1775710090,"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+...","rev": "4c1018dae018162ec878d42fec712642d214fdfa",
Le flake.lock fige automatiquement la version de nixpkgs. C’est le
principal avantage sur shell.nix classique.
nix-shell vs nix develop : quand utiliser lequel ?
Section intitulée « nix-shell vs nix develop : quand utiliser lequel ? »| Critère | nix-shell + shell.nix | nix develop + flake.nix |
|---|---|---|
| Verrouillage | Manuel (fetchTarball + sha256) | Automatique (flake.lock) |
| Prérequis | Aucun | Dépôt Git obligatoire |
| Reproductibilité | Bonne si pinné | Garantie par le lock |
| Simplicité | Plus simple à démarrer | Plus verbeux au début |
| Recommandation | Projets simples, scripts | Projets d’équipe, CI |
Modulariser son environnement
Section intitulée « Modulariser son environnement »Quand le shell.nix grandit, séparez la configuration dans des fichiers
dédiés.
Structure du projet
Section intitulée « Structure du projet »mon-projet/├── shell.nix # point d'entrée├── config.nix # variables du projet└── python-env.nix # environnement Pythonconfig.nix — les variables
Section intitulée « config.nix — les variables »{ projectName = "demo-api"; projectVersion = "1.0.0"; debugMode = true; flaskPort = 5000;}python-env.nix — l’environnement Python
Section intitulée « python-env.nix — l’environnement Python »{ pkgs }:
pkgs.python312.withPackages (ps: [ ps.requests ps.flask ps.pytest])Ce fichier est une fonction qui attend pkgs en argument.
shell.nix — assemblage
Section intitulée « shell.nix — assemblage »{ pkgs ? import <nixpkgs> {} }:
let config = import ./config.nix; pythonEnv = import ./python-env.nix { inherit pkgs; };
debugTools = if config.debugMode then with pkgs; [ htop ncdu ] else [];inpkgs.mkShell { name = "${config.projectName}-dev";
packages = with pkgs; [ pythonEnv git ripgrep ] ++ debugTools;
PROJECT_NAME = config.projectName; PROJECT_VERSION = config.projectVersion; FLASK_RUN_PORT = toString config.flaskPort;
shellHook = '' echo "Projet: ${config.projectName} v${config.projectVersion}" echo "Debug: ${if config.debugMode then "ON" else "OFF"}" '';}nix-shell --run "echo \$PROJECT_NAME \$PROJECT_VERSION \$FLASK_RUN_PORT && which htop"Projet: demo-api v1.0.0Debug: ONdemo-api 1.0.0 5000/nix/store/zalk6ygj90a1d1jyk6rn4ha22fh19gzd-htop-3.4.1/bin/htopinherit pkgs est un raccourci pour pkgs = pkgs — il transmet la
variable du même nom. La modularisation est plus approfondie dans le
guide sur l’import, la factorisation et le pinning.
Charger l’environnement automatiquement avec direnv
Section intitulée « Charger l’environnement automatiquement avec direnv »direnv charge automatiquement l’environnement Nix
quand vous entrez dans le dossier du projet. Plus besoin de taper
nix-shell manuellement.
-
Installez direnv et nix-direnv :
Fenêtre de terminal nix profile add nixpkgs#direnv nixpkgs#nix-direnv -
Activez le hook shell (ajoutez à
~/.bashrcou~/.zshrc) :Fenêtre de terminal eval "$(direnv hook bash)" # ou zsh -
Créez
.envrcà la racine du projet :.envrc use nixOu pour les flakes :
.envrc use flake -
Autorisez le répertoire :
Fenêtre de terminal direnv allow
Désormais, chaque cd mon-projet/ charge automatiquement l’environnement
Nix, et cd .. le décharge. Les outils apparaissent et disparaissent
sans intervention.
L’isolation en pratique
Section intitulée « L’isolation en pratique »Hors du shell Nix, seul le Python système (Debian) est disponible. Dans le shell, Nix fournit ses propres versions — tout est isolé :
=== HORS nix-shell ===htop: introuvablePython 3.11.2 ← Python Debian
=== DANS nix-shell ===/nix/store/.../bin/htop ← htop NixPython 3.12.13 ← Python Nix
=== APRÈS nix-shell ===htop: disparu ← retour à l'état initialChaque projet peut avoir sa propre version de Python, Node.js ou Rust
sans conflits. Plus besoin de pyenv, nvm, rustup pour gérer les
versions par projet.
Comparer avec venv, nvm et Docker
Section intitulée « Comparer avec venv, nvm et Docker »| Critère | venv / nvm | Docker | Nix (shell.nix / flake.nix) |
|---|---|---|---|
| Portée | Un seul langage | Système complet | Tous les outils |
| Overhead | Aucun | Conteneur (RAM, disque) | Aucun (accès direct) |
| Reproductibilité | requirements.txt / .nvmrc | Dockerfile | shell.nix / flake.lock |
| Isolation | Bibliothèques uniquement | Totale (FS, réseau…) | Binaires et bibliothèques |
| CI | pip install + nvm use | docker run | nix-shell —run |
| Partage | Fichier texte | Image (Docker Hub) | Fichier Nix versionné |
- venv / nvm : limités à un seul langage ; Nix gère tout.
- Docker : isolation totale mais plus lourd ; Nix n’ajoute pas de couche.
- Nix : le meilleur compromis pour les environnements de développement.
Dépannage courant
Section intitulée « Dépannage courant »| Symptôme | Cause probable | Solution |
|---|---|---|
nix-shell ne trouve pas un paquet | Nom incorrect | nix search nixpkgs <nom> pour trouver le bon nom |
import <nixpkgs> échoue | Pas de channel configuré | nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs && nix-channel --update |
| Python ne voit pas les bibliothèques | withPackages manquant | Utiliser python312.withPackages (ps: [ ps.xxx ]) |
Changements dans shell.nix non pris en compte | Cache direnv | direnv reload ou quitter et relancer nix-shell |
nix develop échoue | Pas de dépôt Git | git init && git add flake.nix |
| shellHook ne s’exécute pas | Syntaxe Nix incorrecte | Vérifier les '' (multilignes) et les ${} (interpolation) |
À retenir
Section intitulée « À retenir »- Un fichier
shell.nixouflake.nixà la racine du projet décrit l’environnement complet : langages, outils CLI, variables d’environnement. pkgs.mkShellest la fonction centrale — elle prend une liste de paquets, unshellHooket des variables d’environnement.python312.withPackagescrée un Python avec ses bibliothèques, sanspip install.- Toute clé inconnue de
mkShelldevient une variable d’environnement exportée. nix develop(flakes) ajoute le verrouillage automatique des versions — privilégiez-le pour les projets d’équipe.- direnv charge l’environnement automatiquement au
cd— c’est le confort ultime au quotidien. - Les outils n’existent que dans le shell Nix — l’isolation est totale.