Aller au contenu

Nix, le gestionnaire de paquets universel

Mise à jour :

logo nix

Sur les systèmes GNU/Linux, chaque famille de distribution utilise son propre gestionnaire de paquets : APT pour Debian, DNF pour Fedora, Pacman pour Arch Linux… Mais il existe une alternative qui fonctionne sur n’importe quelle distribution Linux et même macOS : Nix.

Nix adopte une approche radicalement différente des gestionnaires traditionnels. Au lieu de modifier le système de fichiers global (/usr/bin, /usr/lib…), Nix stocke chaque paquet dans un emplacement isolé avec toutes ses dépendances. Cette isolation garantit qu’un paquet ne peut jamais “casser” un autre programme, même si les deux nécessitent des versions différentes d’une même bibliothèque.

Dans ce guide, je vais vous présenter les concepts fondamentaux de Nix, son installation, ses commandes essentielles et comment l’utiliser efficacement au quotidien.

Qu’est-ce que Nix ?

Nix est à la fois :

  • Un gestionnaire de paquets (comme apt ou dnf)
  • Un langage de programmation fonctionnel pour décrire des paquets
  • Une philosophie de gestion du logiciel basée sur l’immutabilité

Les concepts clés à comprendre

Avant de commencer, voici les termes que vous rencontrerez souvent :

TermeDéfinition
StoreLe répertoire /nix/store/ où Nix stocke tous les paquets
DérivationUne “recette” qui décrit comment construire un paquet
HashUne empreinte unique calculée à partir des sources et dépendances
ProfilUn ensemble de liens symboliques vers les paquets que vous utilisez
GénérationUn instantané de votre profil à un moment donné
ChannelUn dépôt de paquets Nix (ancienne méthode)
FlakeUn projet Nix avec des dépendances verrouillées (méthode moderne)
NixpkgsLe dépôt principal contenant plus de 100 000 paquets

Paradigme déclaratif vs impératif

La plupart des gestionnaires de paquets sont impératifs : vous exécutez une séquence de commandes (apt install, apt remove…) et l’état final dépend de l’ordre des opérations.

Nix peut fonctionner de façon déclarative : vous décrivez l’état souhaité (“je veux Python 3.12 et Node.js 20”) et Nix calcule comment y arriver. Si vous partagez cette description, quelqu’un d’autre obtient exactement le même environnement.

# Approche impérative (traditionnelle)
apt install python3 # Quelle version ? Dépend du système
apt install nodejs # Peut créer des conflits
# Approche déclarative (Nix)
# Fichier flake.nix
packages = [ python312 nodejs_20 ]; # Versions explicites, reproductibles

Pourquoi utiliser Nix ?

Nix résout des problèmes que les gestionnaires traditionnels ne peuvent pas résoudre. Voici les avantages concrets :

Reproductibilité garantie

Deux machines avec la même configuration Nix obtiennent exactement le même résultat, byte pour byte. C’est fondamental pour :

  • Le travail en équipe : tout le monde a le même environnement
  • L’intégration continue : les builds locaux et CI sont identiques
  • Le débogage : reproduire un bug devient trivial
# Problème classique
"Ça marche pas sur ma machine !" 🤷
# Avec Nix
"Ça marchera partout, c'est le même hash." ✓

Isolation totale

Chaque paquet est stocké dans /nix/store/ avec ses dépendances exactes. Cela élimine le fameux “dependency hell” :

# Situation problématique avec apt
Projet A → nécessite libssl 1.1
Projet B → nécessite libssl 3.0
→ Conflit ! Un seul peut être installé
# Avec Nix
/nix/store/abc123-openssl-1.1.1/
/nix/store/def456-openssl-3.0.0/
→ Les deux coexistent sans problème

Rollback instantané

Chaque modification crée une nouvelle génération. En cas de problème après une mise à jour, retour arrière en une commande :

Terminal window
# Oups, la mise à jour a cassé quelque chose
nix profile rollback
# Système restauré à l'état précédent en 2 secondes

Environnements temporaires

Tester un outil sans l’installer globalement. Parfait pour :

  • Essayer un logiciel avant de s’engager
  • Utiliser un outil une seule fois
  • Garder le système propre
Terminal window
# Tester cowsay sans l'installer
nix run nixpkgs#cowsay -- "Test rapide !"
# À la fin, rien n'est installé sur le système

Multi-versions simultanées

Plusieurs versions d’un même logiciel coexistent sans interférence :

Terminal window
# Besoin de Python 3.10 pour un vieux projet ET Python 3.12 pour un nouveau ?
nix shell nixpkgs#python310 # Dans le terminal 1
nix shell nixpkgs#python312 # Dans le terminal 2
# Les deux fonctionnent simultanément

Installation de Nix

Nix peut s’installer sur n’importe quelle distribution Linux ou macOS, sans interférer avec le gestionnaire de paquets existant. Vous pouvez utiliser Nix en parallèle d’apt, dnf ou pacman.

Prérequis

Avant d’installer Nix, assurez-vous d’avoir :

  • curl : pour télécharger l’installateur
  • Droits sudo : pour l’installation multi-user
  • Espace disque : au moins 5 Go pour /nix (peut grandir significativement)
Terminal window
# Vérifier que curl est installé
which curl || sudo apt install curl # ou dnf, pacman...

Choisir le mode d’installation

Nix propose deux modes d’installation. Le choix dépend de votre situation :

ModeAvantagesInconvénientsRecommandé pour
Single-userSimple, pas de daemonUn seul utilisateurPoste personnel, tests
Multi-userSécurisé, plusieurs utilisateursNécessite root, daemonServeurs, machines partagées

Installation single-user

Pour une machine personnelle où vous êtes le seul utilisateur. C’est le mode le plus simple pour débuter :

Terminal window
# Télécharger et exécuter l'installateur
sh <(curl -L https://nixos.org/nix/install) --no-daemon
  1. L’installateur crée le répertoire /nix/store/
  2. Il ajoute la configuration dans ~/.profile ou ~/.bash_profile
  3. Il installe les commandes Nix dans votre PATH

Installation multi-user

Pour une machine partagée ou un serveur. Ce mode est plus sécurisé car les builds sont isolés dans un daemon dédié :

Terminal window
# Installation avec daemon (nécessite sudo)
sh <(curl -L https://nixos.org/nix/install) --daemon

Cette installation :

  • Crée un groupe nixbld avec des utilisateurs dédiés aux builds
  • Lance un daemon nix-daemon via systemd
  • Configure /etc/nix/nix.conf pour les paramètres globaux
  • Permet à plusieurs utilisateurs de partager le même store
Terminal window
# Vérifier que le daemon fonctionne (après installation)
systemctl status nix-daemon

Vérifier l’installation

Testez que Nix fonctionne correctement :

Terminal window
# Afficher la version de Nix
nix --version
# Exemple de sortie : nix (Nix) 2.18.1
# Premier test : exécuter hello sans l'installer
nix run nixpkgs#hello
Hello, world!

Si la commande affiche “Hello, world!”, félicitations ! Nix est correctement installé et les flakes sont activés.

Fonctionnement du Nix Store

Pour bien comprendre Nix, il est essentiel de saisir comment fonctionne le Nix Store. C’est le cœur de l’architecture et ce qui différencie Nix de tous les autres gestionnaires de paquets.

Où sont stockés les paquets ?

Contrairement aux gestionnaires traditionnels qui installent dans /usr/bin, /usr/lib, etc., Nix stocke tout dans /nix/store/. Chaque paquet a son propre répertoire avec un hash unique :

/nix/store/aaaa1111...-python-3.12.0/
├── bin/
│ └── python3
├── lib/
│ └── libpython3.12.so
└── include/
└── python3.12/
/nix/store/bbbb2222...-python-3.10.0/
├── bin/
│ └── python3
└── ...
/nix/store/cccc3333...-nodejs-20.10.0/
└── ...

Chaque paquet vit dans son propre répertoire, complètement isolé.

Qu’est-ce que ce hash ?

Le hash (ex: aaaa1111...) n’est pas aléatoire. Il est calculé à partir de tout ce qui entre dans la construction du paquet :

  • Le code source
  • Les dépendances (avec leurs propres hashs)
  • Les options de compilation
  • Le compilateur utilisé
  • Les variables d’environnement
Hash = f(sources + dépendances + options + compilateur + ...)

Si une seule option de compilation change, le hash change, et c’est un nouveau paquet dans le store.

Avantages de cette approche

Problème classiqueSolution avec Nix Store
Conflit de versionsChaque version a son propre répertoire
Dépendance casséeChaque paquet embarque ses dépendances exactes
Installation partielleAtomique : tout ou rien
Mise à jour ratéeRollback instantané vers l’état précédent
”Ca marchait hier”Anciennes versions toujours disponibles

Les profils et les liens symboliques

Si tout est dans /nix/store/, comment les commandes sont-elles accessibles ?

Nix utilise des liens symboliques pour créer votre environnement :

~/.nix-profile/bin/python -> /nix/store/aaaa1111...-python-3.12.0/bin/python3
~/.nix-profile/bin/htop -> /nix/store/dddd4444...-htop-3.3.0/bin/htop

Votre PATH contient ~/.nix-profile/bin, qui contient des liens vers le store. Installer un paquet = ajouter un lien. Supprimer = retirer le lien.

Les générations

Chaque modification de votre profil crée une nouvelle génération. C’est comme un système de versioning pour votre environnement.

Génération 1 : python, htop
↓ (nix profile install nodejs)
Génération 2 : python, htop, nodejs
↓ (nix profile remove python)
Génération 3 : htop, nodejs
↓ (nix profile rollback)
Génération 2 : python, htop, nodejs ← retour arrière

Commandes pour gérer les générations :

Terminal window
# Voir l'historique des générations
nix profile history
# Exemple de sortie :
# Version 3 (2024-01-15):
# flake:nixpkgs#htop: 3.2.0 -> 3.3.0
# Revenir à la génération précédente
nix profile rollback
# Revenir à une génération spécifique (par numéro)
nix profile switch 2
# Supprimer les anciennes générations (libère de l'espace après garbage collection)
nix profile wipe-history --older-than 30d

Les commandes essentielles de Nix

Nix propose deux syntaxes de commandes :

SyntaxeCommandesCaractéristiques
Anciennenix-env, nix-shell, nix-buildStable, documentée partout
Nouvellenix profile, nix shell, nix buildPlus claire, nécessite les flakes

Je présente les deux car vous rencontrerez les deux dans la documentation et les tutoriels. La nouvelle syntaxe est recommandée pour les nouveaux projets.

Rechercher un paquet

Avant d’installer un paquet, il faut connaître son nom exact dans nixpkgs.

Terminal window
# Rechercher un paquet par mot-clé
nix search nixpkgs htop
# Exemple de sortie :
# * legacyPackages.x86_64-linux.htop (3.3.0)
# An interactive process viewer

Installer un paquet globalement

Installer un paquet le rend disponible dans votre PATH en permanence.

Terminal window
# Syntaxe : nix profile install nixpkgs#<nom_du_paquet>
nix profile install nixpkgs#htop
# Installer plusieurs paquets à la fois
nix profile install nixpkgs#htop nixpkgs#ripgrep nixpkgs#fzf

Lister les paquets installés

Voir tous les paquets dans votre profil actuel :

Terminal window
nix profile list
# Exemple de sortie :
# Index: 0
# Name: htop
# Path: /nix/store/abc123...-htop-3.3.0

L’index est important pour les commandes de suppression.

Mettre à jour les paquets

Les mises à jour dans Nix sont atomiques : soit tout réussit, soit rien ne change. Pas de système à moitié mis à jour.

Terminal window
# Mettre à jour TOUS les paquets
nix profile upgrade '.*'
# Mettre à jour un paquet spécifique (par index)
nix profile upgrade 0
# Mettre à jour par nom de paquet
nix profile upgrade packages.x86_64-linux.htop

Supprimer un paquet

Supprimer un paquet le retire de votre PATH, mais ne libère pas immédiatement l’espace disque. Le paquet reste dans /nix/store/ jusqu’au prochain garbage collection.

Terminal window
# D'abord, trouver l'index du paquet
nix profile list
# Index: 0
# Name: htop
# Supprimer par index
nix profile remove 0
# Ou supprimer par nom (regex)
nix profile remove '.*htop.*'

Tester un outil sans l’installer

C’est l’une des fonctionnalités les plus puissantes de Nix : utiliser un logiciel temporairement sans polluer le système. Idéal pour :

  • Tester un outil avant de décider de l’installer
  • Utiliser un logiciel pour une tâche ponctuelle
  • Travailler sur un projet sans modifier votre environnement global

Lance un programme et se termine :

Terminal window
# Exécuter cowsay (le -- sépare les options nix des arguments du programme)
nix run nixpkgs#cowsay -- "Hello Nix!"
# Vérifier une version de Python sans l'installer
nix run nixpkgs#python312 -- --version
# Tester un outil réseau
nix run nixpkgs#nmap -- -sP 192.168.1.0/24

Nettoyer le store

Avec le temps, le Nix store accumule les anciennes versions des paquets. C’est intentionnel : cela permet le rollback. Mais l’espace disque peut devenir conséquent.

Terminal window
# Voir la taille actuelle du store
du -sh /nix/store
# Exemple : 15G /nix/store

Comprendre le garbage collection

Nix ne supprime jamais un paquet automatiquement. Un paquet n’est supprimé que si :

  1. Aucune génération n’y fait référence
  2. Vous lancez explicitement le garbage collector
Terminal window
# Supprimer les générations de plus de 30 jours
nix-collect-garbage --delete-older-than 30d
# Supprimer TOUTES les anciennes générations (garder uniquement l'actuelle)
nix-collect-garbage -d
# Nouvelle syntaxe : supprimer les générations de plus de 14 jours
nix profile wipe-history --older-than 14d && nix-collect-garbage

Optimiser le store

Nix peut dédupliquer les fichiers identiques dans le store (hard links) :

Terminal window
# Analyser et dédupliquer le store
nix store optimise
# Peut prendre plusieurs minutes sur un gros store

Cette opération est sûre et peut récupérer plusieurs Go d’espace.

Les Flakes : gestion moderne des dépendances

Les flakes sont l’évolution majeure de Nix. Ils résolvent un problème fondamental : la reproductibilité entre machines.

Le problème avant les flakes

Avant les flakes, le résultat d’un build dépendait des channels installés sur la machine. Chaque utilisateur pouvait avoir une version différente de nixpkgs :

# Machine A (channel mis à jour hier)
nix-shell -p python312
→ Python 3.12.1
# Machine B (channel vieux de 3 mois)
nix-shell -p python312
→ Python 3.12.0 (ou erreur si le paquet n'existait pas)

Deux personnes travaillant sur le même projet obtenaient des résultats différents. Pas très “reproductible” !

La solution : le verrouillage des dépendances

Les flakes apportent le verrouillage des dépendances via un fichier flake.lock, similaire à :

  • package-lock.json en Node.js
  • poetry.lock en Python
  • Cargo.lock en Rust
  • go.sum en Go

Ce fichier enregistre les versions exactes de toutes les dépendances, y compris nixpkgs. Quand quelqu’un clone votre projet, il obtient exactement le même environnement.

Structure d’un flake

Un projet avec flake contient au minimum deux fichiers :

mon-projet/
├── flake.nix # Déclaration des dépendances et outputs
└── flake.lock # Versions exactes (généré automatiquement, à commiter)

Anatomie d’un flake.nix

Voici un exemple commenté :

{
# Description du projet (optionnelle mais recommandée)
description = "Mon projet avec Nix";
# === INPUTS ===
# Les dépendances du flake (d'où viennent les paquets)
inputs = {
# nixpkgs est le dépôt principal de paquets Nix
# On utilise la branche stable 24.05
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
# On peut ajouter d'autres sources
# flake-utils.url = "github:numtide/flake-utils";
};
# === OUTPUTS ===
# Ce que le flake "produit" (environnements, paquets, configurations...)
outputs = { self, nixpkgs }:
let
# Architecture cible (x86_64-linux, aarch64-darwin...)
system = "x86_64-linux";
# Charger les paquets pour cette architecture
pkgs = nixpkgs.legacyPackages.${system};
in {
# Un environnement de développement (accessible via `nix develop`)
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
python312
nodejs_20
git
];
# Commande exécutée à l'entrée du shell
shellHook = ''
echo "Bienvenue dans l'environnement de développement !"
'';
};
};
}

Utiliser un flake

  1. Créer un nouveau flake (si vous partez de zéro) :

    Terminal window
    # Initialiser un flake basique
    nix flake init
  2. Entrer dans l’environnement de développement :

    Terminal window
    # Depuis le dossier contenant flake.nix
    nix develop
    # Ou depuis un dépôt distant
    nix develop github:owner/repo
  3. Mettre à jour les dépendances (quand vous voulez les dernières versions) :

    Terminal window
    nix flake update
    # Met à jour flake.lock
  4. Commiter flake.lock pour que tout le monde ait les mêmes versions :

    Terminal window
    git add flake.nix flake.lock
    git commit -m "chore: init nix flake"

Bonnes pratiques avec Nix

Préférer les flakes aux channels

Les channels (nix-channel) sont l’ancienne méthode de gestion des sources de paquets. Bien qu’ils fonctionnent encore, les flakes sont recommandés :

AspectChannelsFlakes
ReproductibilitéVariable selon la machineGarantie via flake.lock
VersionnementManuelIntégré
CollaborationDifficileNaturelle (commit le lock)
SyntaxeAncienneModerne et claire

Nettoyer régulièrement le store

Le store peut atteindre plusieurs dizaines de Go. Planifiez un nettoyage :

# Script de nettoyage à exécuter régulièrement (ou en cron)
#!/bin/bash
echo "Suppression des générations de plus de 14 jours..."
nix profile wipe-history --older-than 14d
echo "Garbage collection..."
nix-collect-garbage
echo "Optimisation du store..."
nix store optimise
echo "Taille actuelle du store :"
du -sh /nix/store

Utiliser des environnements par projet

Plutôt que d’installer globalement tous vos outils de développement, créez un flake.nix par projet. Les avantages :

  • Documentation : le flake.nix liste exactement ce dont le projet a besoin
  • Onboarding : un nouveau développeur fait nix develop et c’est prêt
  • Isolation : pas de conflit entre le projet A qui utilise Node 18 et le projet B qui utilise Node 20
  • CI/CD : les mêmes outils en local et sur le serveur de build

Versionner vos configurations

Si vous utilisez Nix pour configurer votre système (Home Manager, NixOS), versionnez vos fichiers dans Git :

dotfiles/
├── flake.nix # Point d'entrée
├── flake.lock # Versions verrouillées
├── home.nix # Configuration Home Manager
└── hosts/
├── laptop.nix # Config spécifique au laptop
└── desktop.nix # Config spécifique au desktop

Avantages :

  • Historique : voir l’évolution de votre configuration
  • Rollback : revenir à une config précédente via Git
  • Synchronisation : même config sur plusieurs machines
  • Sauvegarde : votre environnement est sur GitHub/GitLab

Éviter les anti-patterns

À éviterPourquoiAlternative
Installer globalement toutPollue le profilUtiliser nix shell ou flakes par projet
Ne jamais faire de GCStore qui explosePlanifier un nettoyage mensuel
Ignorer flake.lockPerte de reproductibilitéToujours commiter le lock
Mélanger channels et flakesConfusionChoisir l’un ou l’autre

Dépannage courant avec Nix

Nix peut parfois être déroutant, surtout au début. Voici les problèmes les plus fréquents et leurs solutions.

”command not found: nix” après installation

Les variables d’environnement ne sont pas chargées :

Terminal window
# Solution 1 : ouvrir un nouveau terminal
# Solution 2 : charger manuellement le profil
. ~/.nix-profile/etc/profile.d/nix.sh
# Solution 3 : vérifier que le fichier existe
ls -la ~/.nix-profile/etc/profile.d/

Le build échoue

Plusieurs causes possibles :

Terminal window
# Afficher plus de détails sur l'erreur
nix build --verbose
# Voir les logs complets d'un build échoué
nix log /nix/store/xxxxx-nom-du-paquet
# Reconstruire sans cache (si le cache est suspect)
nix build --rebuild

“error: experimental feature ‘flakes’ is disabled”

Les flakes ne sont pas activés :

Terminal window
# Créer ou modifier le fichier de configuration
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
# Vérifier que c'est bien pris en compte
cat ~/.config/nix/nix.conf

Le store est corrompu

Rare, mais peut arriver après un crash ou un disque plein :

Terminal window
# Vérifier l'intégrité du store (peut être long)
nix store verify --all
# Réparer les chemins cassés
nix store repair --all
# Si le problème persiste, reconstruire le chemin problématique
nix build --rebuild nixpkgs#nom-du-paquet

Espace disque insuffisant

Terminal window
# Diagnostic : voir la taille du store
du -sh /nix/store
# Identifier les plus gros paquets
du -sh /nix/store/* | sort -hr | head -20
# Nettoyage agressif (supprime TOUT l'historique)
nix-collect-garbage -d
# Optimiser (déduplication)
nix store optimise

Problèmes de permissions (installation multi-user)

Terminal window
# Vérifier que le daemon tourne
systemctl status nix-daemon
# Redémarrer le daemon
sudo systemctl restart nix-daemon
# Vérifier les permissions du store
ls -la /nix/store | head -5
# Devrait appartenir à root:nixbld
# Vérifier que votre utilisateur est dans le bon groupe
groups $USER

“error: cached failure of attribute”

Un build précédent a échoué et est en cache :

Terminal window
# Supprimer le cache des échecs
rm -rf ~/.cache/nix/
# Réessayer le build
nix build nixpkgs#nom-du-paquet

“hash mismatch” lors d’un téléchargement

Le fichier téléchargé ne correspond pas au hash attendu :

Terminal window
# Souvent un problème réseau temporaire. Réessayer :
nix build nixpkgs#nom-du-paquet
# Si le problème persiste, mettre à jour nixpkgs
nix flake update nixpkgs

Pour aller plus loin

Après avoir maîtrisé les bases de Nix, voici les prochaines étapes :

  • Gestion de serveurs : Consultez mes guides sur APT et DNF pour comparer avec les gestionnaires traditionnels
  • NixOS : Découvrez le système d’exploitation qui pousse Nix à son maximum avec mon guide d’introduction à NixOS
  • Systèmes immuables : Comprenez la philosophie des OS immuables dont NixOS fait partie
  • DevOps : Intégrez Nix dans vos pipelines CI/CD pour des builds reproductibles

Documentation officielle

RessourceDescriptionNiveau
Nix ManualRéférence complèteTous
Nix PillsTutoriel progressif pour comprendre Nix en profondeurIntermédiaire
NixOS WikiWiki communautaire avec exemples pratiquesTous
Zero to NixGuide interactif pour débutantsDébutant
nix.devTutoriels et bonnes pratiquesIntermédiaire

Recherche de paquets et options

Communauté

Exemples et templates

Conclusion

Nix représente un changement de paradigme dans la gestion des paquets. Sa courbe d’apprentissage est réelle : le langage Nix, les concepts de store et de dérivations, les flakes… Mais une fois ces concepts assimilés, les bénéfices sont considérables :

  • Reproductibilité : finies les différences “ça marche chez moi”
  • Isolation : fini le “dependency hell”
  • Rollback : finie la peur des mises à jour
  • Documentation : votre environnement est codé et versionné

Je vous conseille de commencer progressivement :

  1. Installez Nix sur votre système actuel (il cohabite avec apt/dnf)
  2. Utilisez nix shell pour tester des outils sans les installer
  3. Créez un premier flake.nix pour un projet de développement
  4. Explorez Home Manager pour gérer vos dotfiles
  5. Si vous êtes convaincu, passez à NixOS !

La communauté Nix est accueillante et active. N’hésitez pas à poser vos questions sur le Discourse ou Matrix.