Nix et NixOS : La Gestion Reproductible de Systèmes et Environnements

Nix et NixOS : gestion reproductible de systèmes et environnements de dev. Flakes, nix develop, Home Manager, devenv.sh et déploiement avec deploy-rs.

Introduction

Combien de fois avez-vous entendu — ou prononcé — la phrase « ça marche sur ma machine » ? Ce problème fondamental du développement logiciel persiste depuis des décennies malgré les conteneurs, les machines virtuelles et les outils de gestion de configuration. La raison est simple : la plupart de ces outils gèrent les changements d'état de manière impérative, sans garantir la reproductibilité.

Nix prend une approche radicalement différente. Inspiré des concepts de programmation fonctionnelle, Nix est un gestionnaire de paquets purement fonctionnel où chaque paquet est défini par ses entrées (code source, dépendances, options de compilation) et produit une sortie déterministe. Si les entrées sont identiques, la sortie est identique — sur n'importe quelle machine, à n'importe quel moment.

Architecture en un coup d'œil

Diagramme - Nix et NixOS : La Gestion Reproductible de Systèmes et Environnements

NixOS pousse cette philosophie encore plus loin : c'est un système d'exploitation Linux entier configuré de manière déclarative. Votre système — services, utilisateurs, réseau, pare-feu, tout — est décrit dans un fichier de configuration. Un changement dans ce fichier produit une nouvelle « génération » du système, avec la possibilité de rollback atomique vers n'importe quelle génération précédente.

En 2025-2026, Nix connaît une croissance explosive. Nixpkgs, son dépôt de paquets, est devenu le plus grand dépôt de paquets au monde avec plus de 100 000 paquets — dépassant l'AUR d'Arch Linux. Les flakes, le nouveau système de composition, ont révolutionné la reproductibilité des environnements de développement. Et des projets comme Home Manager, devenv.sh et Cachix rendent l'écosystème accessible à un public de plus en plus large.

Dans cet article, nous allons explorer en profondeur Nix et NixOS : leur fonctionnement, leur installation, leurs cas d'usage, et comment ils peuvent transformer votre workflow de développement et de déploiement.

Qu'est-ce que Nix ? Le gestionnaire de paquets fonctionnel

Le problème que Nix résout

Les gestionnaires de paquets traditionnels (apt, dnf, pacman, brew) partagent un modèle commun : ils installent les paquets dans des emplacements globaux partagés (/usr/lib, /usr/bin, etc.) et modifient l'état du système de manière impérative et mutable. Ce modèle pose plusieurs problèmes :

  • Conflits de dépendances (dependency hell) : le projet A nécessite OpenSSL 1.1, le projet B nécessite OpenSSL 3.0. Les deux ne peuvent pas coexister dans /usr/lib
  • Non-reproductibilité : installer les mêmes paquets sur deux machines peut produire des résultats différents selon l'ordre d'installation, les mises à jour intermédiaires, etc.
  • Mises à jour destructives : une mise à jour peut casser des logiciels qui dépendaient de la version précédente, sans moyen simple de revenir en arrière
  • Impossible de tester avant de committer : on ne peut pas facilement tester un changement d'état du système sans l'appliquer
  • Pas de rollback fiable : apt remove ne restaure pas l'état précédent du système

Le modèle fonctionnel de Nix

Nix résout ces problèmes en empruntant les concepts de la programmation fonctionnelle pure :

  • Pureté : le résultat d'une « build » ne dépend que de ses entrées explicitement déclarées. Pas d'effets de bord, pas de dépendances implicites sur l'état du système
  • Immutabilité : une fois construit, un paquet ne change jamais. Il n'est pas « mis à jour » — une nouvelle version est un nouveau paquet distinct
  • Adressage par le contenu (content-addressable) : chaque paquet est stocké dans un chemin unique dérivé d'un hash cryptographique de toutes ses entrées
  • Composition : les systèmes complexes sont construits en composant des paquets simples, de manière déterministe

Le Nix Store : /nix/store

Le cœur de Nix est le Nix Store, un répertoire (/nix/store) où chaque paquet est stocké dans un chemin unique basé sur un hash de ses entrées :

# Exemples de chemins dans le Nix Store
/nix/store/w0bgiyx6r9ahqjhpwn7gyp5jbqxs24nl-python3-3.12.7/
/nix/store/a4kif8z5rs3h2grwkzipbx0g12m21dql-python3-3.12.8/
/nix/store/k3bc4bpg1wn0f7n3jb2g7q3l1yvz6g5h-openssl-3.3.2/
/nix/store/m6v2dsh7rp9nz5k0h8j4x1q2w3e4r5t6-nodejs-22.11.0/
/nix/store/p7w3e4r5t6y7u8i9o0a1s2d3f4g5h6j7-nginx-1.27.3/

# Le hash (les 32 premiers caractères) est calculé à partir de :
# - Le code source du paquet
# - Toutes les dépendances (récursivement)
# - Les options de compilation
# - Le compilateur utilisé
# - Les patches appliqués

# Cela signifie que deux versions différentes de Python coexistent
# sans aucun conflit :
ls /nix/store/ | grep python3-3.12
# w0bgiyx6r9ahqjhpwn7gyp5jbqxs24nl-python3-3.12.7
# a4kif8z5rs3h2grwkzipbx0g12m21dql-python3-3.12.8

# Chaque paquet contient sa propre arborescence complète
ls /nix/store/w0bgiyx6r9ahqjhpwn7gyp5jbqxs24nl-python3-3.12.7/
# bin/  include/  lib/  share/

# Les dépendances sont des liens vers d'autres chemins dans le store
ldd /nix/store/w0bgiyx6r9ahqjhpwn7gyp5jbqxs24nl-python3-3.12.7/bin/python3
# /nix/store/k3bc4bpg1wn0f7n3jb2g7q3l1yvz6g5h-openssl-3.3.2/lib/libssl.so.3
# /nix/store/...-glibc-2.40/lib/libc.so.6

Ce modèle permet :

  • Coexistence de versions : plusieurs versions d'un même paquet coexistent sans conflit
  • Reproductibilité : le même hash = le même paquet, garanti
  • Rollback atomique : revenir à une version précédente = pointer vers l'ancien chemin dans le store
  • Garbage collection : les paquets non référencés peuvent être supprimés avec nix-collect-garbage
  • Partage : si deux utilisateurs ont besoin du même paquet, il n'est stocké qu'une seule fois

Nixpkgs : le plus grand dépôt de paquets au monde

Nixpkgs est le dépôt central de paquets Nix, hébergé sur GitHub (github.com/NixOS/nixpkgs). En 2025, il contient plus de 100 000 paquets, ce qui en fait le plus grand dépôt de paquets de toute distribution Linux. À titre de comparaison :

Dépôt Nombre de paquets (approx. 2025)
Nixpkgs 100 000+
AUR (Arch Linux) ~85 000
Debian (stable) ~60 000
Fedora ~55 000
Homebrew ~7 000

Nixpkgs est maintenu par une communauté de plus de 6 000 contributeurs et suit un modèle de branches :

  • nixpkgs-unstable : les dernières versions de tous les paquets (rolling release)
  • nixos-24.11 : branche stable, mise à jour pendant ~7 mois après la release
  • nixos-25.05 : la prochaine release stable (mai 2025)

Installer Nix

Nix peut être installé sur n'importe quelle distribution Linux et sur macOS. Il ne remplace pas votre gestionnaire de paquets existant — il coexiste avec lui. Vous pouvez utiliser Nix aux côtés d'apt, dnf, pacman ou brew sans aucun conflit.

Installation recommandée : le Determinate Nix Installer

# Installation recommandée avec le Determinate Nix Installer
# (installation multi-user avec flakes activés par défaut)
curl --proto '=https' --tlsv1.2 -sSf -L \
  https://install.determinate.systems/nix | sh -s -- install

# Alternative : installateur officiel NixOS
sh <(curl -L https://nixos.org/nix/install) --daemon

# Vérifier l'installation
nix --version
# nix (Nix) 2.25.3

# Tester avec un paquet
nix run nixpkgs#hello
# Hello, world!

# Lancer un shell avec un paquet temporaire (sans installation permanente)
nix shell nixpkgs#python3 nixpkgs#nodejs
python3 --version  # Python 3.12.x
node --version     # v22.x.x
exit  # Les paquets disparaissent

# Chercher un paquet
nix search nixpkgs firefox
nix search nixpkgs "python3.*packages"

Installation sur macOS

# Sur macOS, Nix fonctionne parfaitement
curl --proto '=https' --tlsv1.2 -sSf -L \
  https://install.determinate.systems/nix | sh -s -- install

# Nix crée un volume APFS dédié pour /nix/store sur macOS
# (nécessaire car le rootfs macOS est en lecture seule)
df -h /nix
# /dev/disk1s7  460Gi  2.1Gi  458Gi  1%  /nix

# Utiliser des paquets Linux sur macOS
nix shell nixpkgs#ripgrep nixpkgs#fd nixpkgs#bat nixpkgs#jq
rg --version  # Compilé nativement pour macOS/ARM64

nix-shell : environnements de développement reproductibles

nix-shell est l'un des outils les plus puissants de Nix. Il permet de créer des environnements de développement éphémères et reproductibles contenant exactement les outils dont vous avez besoin, sans polluer votre système :

# Shell temporaire avec Python, Node.js et PostgreSQL client
nix-shell -p python3 nodejs postgresql

# Dans ce shell :
python3 --version  # 3.12.x
node --version     # 22.x.x
psql --version     # 16.x
exit  # Tout disparaît

# Shell avec des paquets Python spécifiques
nix-shell -p 'python3.withPackages (ps: with ps; [ requests flask sqlalchemy ])'
python3 -c "import flask; print(flask.__version__)"  # Fonctionne !

# Shell pour le développement Rust
nix-shell -p rustc cargo rust-analyzer clippy rustfmt

# Shell pour le développement Go
nix-shell -p go gopls golangci-lint

# Script reproductible avec nix-shell shebang
cat << 'EOF' > script.py
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ requests beautifulsoup4 ])"

import requests
from bs4 import BeautifulSoup

resp = requests.get("https://example.com")
soup = BeautifulSoup(resp.text, 'html.parser')
print(soup.title.string)
EOF
chmod +x script.py
./script.py  # Les dépendances sont automatiquement disponibles

Flakes : le futur de Nix

Les flakes sont le système moderne de composition de Nix, introduit pour résoudre les problèmes de reproductibilité du Nix classique. Un flake est un dépôt Nix avec deux fichiers clés :

  • flake.nix : la définition déclarative du projet (entrées, sorties)
  • flake.lock : le verrouillage des versions exactes de toutes les entrées (comme package-lock.json pour npm)

Les flakes garantissent que deux personnes exécutant le même flake obtiennent exactement le même résultat, peu importe leur machine ou le moment.

Anatomie d'un flake.nix

# flake.nix — Environnement de développement reproductible
# pour un projet Python/FastAPI avec PostgreSQL et Redis
{
  description = "Environnement de développement pour mon-api-projet";

  # === ENTRÉES ===
  # Les sources externes dont dépend ce flake
  inputs = {
    # Nixpkgs : le dépôt de paquets
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";

    # Flake-utils : utilitaires pour simplifier les flakes multi-plateformes
    flake-utils.url = "github:numtide/flake-utils";

    # Poetry2nix : intégration Poetry/Nix pour les projets Python
    poetry2nix = {
      url = "github:nix-community/poetry2nix";
      inputs.nixpkgs.follows = "nixpkgs";  # Réutiliser le même nixpkgs
    };
  };

  # === SORTIES ===
  # Ce que ce flake produit
  outputs = { self, nixpkgs, flake-utils, poetry2nix }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = true;  # Autoriser les paquets non-libres si nécessaire
        };

        # Version de Python avec les packages nécessaires au développement
        pythonEnv = pkgs.python312.withPackages (ps: with ps; [
          # Frameworks
          fastapi
          uvicorn
          sqlalchemy
          alembic
          pydantic

          # Base de données
          psycopg2
          redis

          # Outils de dev
          pytest
          pytest-cov
          pytest-asyncio
          black
          ruff
          mypy
          ipython

          # HTTP
          httpx
          requests
        ]);

      in {
        # === DEVSHELL ===
        # L'environnement de développement, activé avec `nix develop`
        devShells.default = pkgs.mkShell {
          name = "mon-api-dev";

          # Paquets disponibles dans le shell
          buildInputs = [
            # Python avec ses packages
            pythonEnv

            # Base de données
            pkgs.postgresql_16
            pkgs.redis

            # Outils CLI
            pkgs.curl
            pkgs.jq
            pkgs.httpie
            pkgs.just          # Task runner (alternative à Make)
            pkgs.watchexec     # Relancer une commande au changement de fichiers

            # Infrastructure
            pkgs.docker-compose
            pkgs.terraform
            pkgs.ansible

            # Outils de qualité
            pkgs.pre-commit
            pkgs.shellcheck
            pkgs.hadolint      # Linter pour Dockerfile

            # Git
            pkgs.git
            pkgs.git-crypt
            pkgs.delta         # Diff amélioré
          ];

          # Variables d'environnement
          env = {
            DATABASE_URL = "postgresql://dev:dev@localhost:5432/myapp";
            REDIS_URL = "redis://localhost:6379";
            PYTHONDONTWRITEBYTECODE = "1";
            PYTHONUNBUFFERED = "1";
          };

          # Script exécuté à l'entrée dans le shell
          shellHook = ''
            echo "╔══════════════════════════════════════════╗"
            echo "║  Environnement de développement actif    ║"
            echo "║  Python: $(python3 --version)            ║"
            echo "║  PostgreSQL: $(pg_config --version)      ║"
            echo "╚══════════════════════════════════════════╝"

            # Créer un virtualenv local pour les dépendances Python additionnelles
            if [ ! -d .venv ]; then
              echo "Création du virtualenv..."
              python3 -m venv .venv
            fi
            source .venv/bin/activate

            # Alias utiles
            alias run="uvicorn app.main:app --reload --host 0.0.0.0 --port 8000"
            alias test="pytest -v --cov=app tests/"
            alias lint="ruff check . && mypy app/"
            alias fmt="black . && ruff check --fix ."
            alias db-migrate="alembic upgrade head"
            alias db-revision="alembic revision --autogenerate -m"
          '';
        };

        # === PACKAGES ===
        # Le paquet buildable du projet
        packages.default = pkgs.python312Packages.buildPythonApplication {
          pname = "mon-api";
          version = "1.0.0";
          src = ./.;
          propagatedBuildInputs = with pkgs.python312Packages; [
            fastapi uvicorn sqlalchemy psycopg2 redis pydantic alembic
          ];
        };

        # === IMAGE DOCKER ===
        # Construire une image Docker optimisée via Nix
        packages.docker = pkgs.dockerTools.buildLayeredImage {
          name = "mon-api";
          tag = "latest";
          contents = [ self.packages.${system}.default ];
          config = {
            Cmd = [ "${self.packages.${system}.default}/bin/mon-api" ];
            ExposedPorts = { "8000/tcp" = {}; };
            Env = [
              "PYTHONUNBUFFERED=1"
            ];
          };
        };
      }
    );
}

Utiliser un flake

# Entrer dans l'environnement de développement
nix develop

# Ou depuis n'importe où (sans cloner le repo)
nix develop github:user/mon-projet

# Mettre à jour les dépendances (flake.lock)
nix flake update

# Mettre à jour une seule entrée
nix flake update nixpkgs

# Construire le paquet
nix build

# Construire l'image Docker
nix build .#docker
docker load < result

# Lancer directement sans construire
nix run

# Afficher les sorties du flake
nix flake show

# Vérifier le flake
nix flake check

Le fichier flake.lock

Le fichier flake.lock est généré automatiquement et verrouille les versions exactes de toutes les entrées. C'est ce qui garantit la reproductibilité :

# flake.lock (extrait simplifié — format JSON)
# Ce fichier est géré automatiquement par Nix
# Il contient les hashes exacts de chaque entrée

# Afficher les entrées verrouillées
nix flake metadata
# Description: Environnement de développement pour mon-api-projet
# Path:        /home/user/projects/mon-api
# Revision:    abc123...
# Last modified: 2025-12-15
# Inputs:
#   ├── flake-utils: github:numtide/flake-utils/...
#   ├── nixpkgs: github:NixOS/nixpkgs/nixos-24.11/...
#   └── poetry2nix: github:nix-community/poetry2nix/...

# Le flake.lock doit être committé dans Git
# pour que tous les développeurs aient les mêmes versions
git add flake.nix flake.lock
git commit -m "feat: add Nix flake for reproducible dev environment"

NixOS : le système d'exploitation déclaratif

NixOS est une distribution Linux qui applique les principes de Nix à l'ensemble du système d'exploitation. Au lieu de configurer votre système avec une série de commandes impératives (apt install, systemctl enable, éditer /etc/nginx/nginx.conf...), vous décrivez l'état souhaité dans un fichier de configuration et NixOS s'occupe de le réaliser.

Le fichier configuration.nix

# /etc/nixos/configuration.nix
# Configuration NixOS complète pour un serveur web/API
{ config, pkgs, lib, ... }:

{
  # === SYSTÈME DE BASE ===
  system.stateVersion = "24.11";

  # Boot loader
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # Kernel
  boot.kernelPackages = pkgs.linuxPackages_latest;

  # === RÉSEAU ===
  networking = {
    hostName = "serveur-prod";
    domain = "example.com";

    # Interface réseau
    interfaces.ens3 = {
      ipv4.addresses = [{
        address = "10.0.0.5";
        prefixLength = 24;
      }];
    };
    defaultGateway = "10.0.0.1";
    nameservers = [ "1.1.1.1" "8.8.8.8" ];

    # Pare-feu déclaratif
    firewall = {
      enable = true;
      allowedTCPPorts = [ 22 80 443 ];
      allowedUDPPorts = [ ];
      # Règles iptables personnalisées si nécessaire
      extraCommands = ''
        iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 5432 -j ACCEPT
      '';
    };
  };

  # === FUSEAU HORAIRE ET LOCALE ===
  time.timeZone = "Europe/Paris";
  i18n.defaultLocale = "fr_FR.UTF-8";
  i18n.extraLocaleSettings = {
    LC_TIME = "fr_FR.UTF-8";
    LC_MONETARY = "fr_FR.UTF-8";
  };

  # === UTILISATEURS ===
  users.users = {
    admin = {
      isNormalUser = true;
      description = "Administrateur";
      extraGroups = [ "wheel" "docker" "networkmanager" ];
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample... admin@workstation"
      ];
      shell = pkgs.zsh;
    };

    deploy = {
      isNormalUser = true;
      description = "Compte de déploiement";
      extraGroups = [ "docker" ];
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample... ci@github"
      ];
    };
  };

  # Interdire la connexion root par mot de passe
  users.users.root.hashedPassword = "!";  # Désactivé

  # === SSH ===
  services.openssh = {
    enable = true;
    settings = {
      PasswordAuthentication = false;
      PermitRootLogin = "no";
      X11Forwarding = false;
      MaxAuthTries = 3;
    };
    # Uniquement clés ED25519 et RSA 4096+
    hostKeys = [
      { path = "/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; }
      { path = "/etc/ssh/ssh_host_rsa_key"; type = "rsa"; bits = 4096; }
    ];
  };

  # === PAQUETS SYSTÈME ===
  environment.systemPackages = with pkgs; [
    # Éditeurs
    vim
    neovim
    helix

    # Outils système
    htop
    btop
    tmux
    git
    curl
    wget
    jq
    yq
    ripgrep
    fd
    bat
    tree
    ncdu
    duf

    # Réseau
    dig
    nmap
    tcpdump
    iperf3
    mtr

    # Conteneurs
    docker
    docker-compose

    # Monitoring
    prometheus-node-exporter
  ];

  # === SERVICES ===

  # Nginx comme reverse proxy
  services.nginx = {
    enable = true;
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;

    virtualHosts = {
      "api.example.com" = {
        forceSSL = true;
        enableACME = true;  # Let's Encrypt automatique
        locations."/" = {
          proxyPass = "http://127.0.0.1:8000";
          proxyWebsockets = true;
          extraConfig = ''
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          '';
        };
        locations."/static/" = {
          root = "/var/www/api";
          extraConfig = ''
            expires 30d;
            add_header Cache-Control "public, immutable";
          '';
        };
      };

      "monitoring.example.com" = {
        forceSSL = true;
        enableACME = true;
        locations."/" = {
          proxyPass = "http://127.0.0.1:3000";  # Grafana
        };
        # Accès restreint par IP
        extraConfig = ''
          allow 10.0.0.0/8;
          deny all;
        '';
      };
    };
  };

  # Let's Encrypt
  security.acme = {
    acceptTerms = true;
    defaults.email = "admin@example.com";
  };

  # PostgreSQL
  services.postgresql = {
    enable = true;
    package = pkgs.postgresql_16;
    settings = {
      max_connections = 200;
      shared_buffers = "256MB";
      effective_cache_size = "1GB";
      work_mem = "4MB";
      maintenance_work_mem = "128MB";
      log_min_duration_statement = 1000;  # Log les requêtes > 1s
    };
    authentication = ''
      local all all trust
      host all all 10.0.0.0/8 md5
    '';
    ensureDatabases = [ "myapp" "myapp_test" ];
    ensureUsers = [
      {
        name = "myapp";
        ensureDBOwnership = true;
      }
    ];
  };

  # Redis
  services.redis.servers.default = {
    enable = true;
    port = 6379;
    bind = "127.0.0.1";
    settings = {
      maxmemory = "256mb";
      maxmemory-policy = "allkeys-lru";
    };
  };

  # Docker
  virtualisation.docker = {
    enable = true;
    autoPrune = {
      enable = true;
      dates = "weekly";
      flags = [ "--all" "--volumes" ];
    };
  };

  # Fail2ban
  services.fail2ban = {
    enable = true;
    maxretry = 5;
    bantime = "1h";
    bantime-increment.enable = true;
  };

  # Automatic garbage collection
  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 30d";
  };

  # Automatic system updates
  system.autoUpgrade = {
    enable = true;
    allowReboot = false;
    dates = "04:00";
    flake = "github:myorg/nixos-config";
  };

  # === NIX SETTINGS ===
  nix.settings = {
    experimental-features = [ "nix-command" "flakes" ];
    auto-optimise-store = true;
    # Cache binaire pour accélérer les builds
    substituters = [
      "https://cache.nixos.org"
      "https://myorg.cachix.org"
    ];
    trusted-public-keys = [
      "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
      "myorg.cachix.org-1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx="
    ];
  };

  # Autoriser les paquets non-libres
  nixpkgs.config.allowUnfree = true;

  # === PROGRAMMES ===
  programs.zsh.enable = true;
  programs.mtr.enable = true;
  programs.gnupg.agent.enable = true;
}

Appliquer la configuration

# Reconstruire le système avec la nouvelle configuration
sudo nixos-rebuild switch

# Tester la configuration sans l'activer au reboot
sudo nixos-rebuild test

# Construire sans activer (vérifier que ça compile)
sudo nixos-rebuild build

# Reconstruire avec un flake distant
sudo nixos-rebuild switch --flake github:myorg/nixos-config#serveur-prod

# Lister les générations du système
nix-env --list-generations --profile /nix/var/nix/profiles/system
# 42  2025-11-15 14:30:00  (current)
# 41  2025-11-10 09:15:00
# 40  2025-11-05 16:45:00

# Rollback à la génération précédente
sudo nixos-rebuild switch --rollback

# Ou choisir une génération spécifique au boot (menu GRUB/systemd-boot)
# Chaque génération est listée dans le menu de démarrage !

Rollbacks atomiques et générations

L'un des avantages les plus puissants de NixOS est le système de générations. Chaque fois que vous exécutez nixos-rebuild switch, une nouvelle génération est créée. Vous pouvez :

  • Lister toutes les générations avec leur date et les changements
  • Revenir à n'importe quelle génération instantanément avec nixos-rebuild switch --rollback
  • Choisir une génération au boot dans le menu du bootloader
  • Différencier les générations pour voir ce qui a changé

Cela signifie qu'une mise à jour qui casse le système n'est jamais un problème irréversible. Un simple reboot avec sélection de la génération précédente restaure un système fonctionnel en quelques secondes.

# Voir les différences entre deux générations
nix store diff-closures /nix/var/nix/profiles/system-41-link /nix/var/nix/profiles/system-42-link
# nginx: 1.26.2 → 1.27.3
# postgresql: 16.3 → 16.4
# linux: 6.11.5 → 6.12.1
# openssl: 3.3.1 → 3.3.2 (CVE-2024-xxxx fixed)

# Nettoyer les anciennes générations (garder les 5 dernières)
sudo nix-collect-garbage --delete-older-than 5d

# Ou garder un nombre spécifique de générations
sudo nix-env --delete-generations +5 --profile /nix/var/nix/profiles/system

Home Manager : les dotfiles déclaratifs

Home Manager est un outil qui applique les principes de Nix à la configuration de l'environnement utilisateur. Au lieu de gérer vos dotfiles manuellement (ou avec des scripts d'installation fragiles), vous les déclarez dans un fichier Nix et Home Manager s'occupe de les déployer.

# home.nix — Configuration Home Manager
{ config, pkgs, ... }:

{
  home.username = "admin";
  home.homeDirectory = "/home/admin";
  home.stateVersion = "24.11";

  # === PAQUETS UTILISATEUR ===
  home.packages = with pkgs; [
    # CLI modernes
    eza           # Remplacement de ls
    bat           # Remplacement de cat
    ripgrep       # Remplacement de grep
    fd            # Remplacement de find
    delta         # Diff amélioré pour Git
    fzf           # Fuzzy finder
    zoxide        # Remplacement de cd (auto-jump)
    starship      # Prompt shell moderne
    lazygit       # TUI pour Git
    yazi          # File manager TUI

    # Développement
    neovim
    direnv
    just
    watchexec

    # Kubernetes
    kubectl
    kubectx
    k9s
    helm
    kustomize

    # Cloud
    awscli2
    terraform
  ];

  # === GIT ===
  programs.git = {
    enable = true;
    userName = "Mon Nom";
    userEmail = "mon@email.com";
    signing = {
      key = "~/.ssh/id_ed25519.pub";
      signByDefault = true;
    };
    delta = {
      enable = true;
      options = {
        navigate = true;
        light = false;
        side-by-side = true;
        line-numbers = true;
      };
    };
    extraConfig = {
      init.defaultBranch = "main";
      pull.rebase = true;
      push.autoSetupRemote = true;
      rerere.enabled = true;
      merge.conflictStyle = "zdiff3";
      diff.algorithm = "histogram";
    };
    aliases = {
      st = "status -sb";
      co = "checkout";
      br = "branch";
      ci = "commit";
      lg = "log --graph --oneline --decorate --all";
      undo = "reset --soft HEAD~1";
      amend = "commit --amend --no-edit";
    };
  };

  # === ZSH ===
  programs.zsh = {
    enable = true;
    autosuggestion.enable = true;
    syntaxHighlighting.enable = true;
    history = {
      size = 50000;
      save = 50000;
      ignoreDups = true;
      ignoreAllDups = true;
      share = true;
    };
    shellAliases = {
      ls = "eza --icons --group-directories-first";
      ll = "eza -la --icons --group-directories-first";
      lt = "eza --tree --icons --level=3";
      cat = "bat";
      grep = "rg";
      find = "fd";
      cd = "z";  # zoxide
      ".." = "cd ..";
      "..." = "cd ../..";
      k = "kubectl";
      kx = "kubectx";
      kn = "kubens";
      tf = "terraform";
      dc = "docker compose";
      lg = "lazygit";
    };
    initExtra = ''
      # Charger les completions Kubernetes
      source <(kubectl completion zsh)

      # Direnv hook
      eval "$(direnv hook zsh)"
    '';
  };

  # === STARSHIP (prompt) ===
  programs.starship = {
    enable = true;
    settings = {
      add_newline = true;
      format = "$all";
      character = {
        success_symbol = "[➜](bold green)";
        error_symbol = "[✗](bold red)";
      };
      git_branch.symbol = " ";
      python.symbol = " ";
      nodejs.symbol = " ";
      rust.symbol = " ";
      nix_shell = {
        symbol = " ";
        format = "via [$symbol$name]($style) ";
      };
      kubernetes = {
        disabled = false;
        symbol = "⎈ ";
      };
    };
  };

  # === DIRENV ===
  programs.direnv = {
    enable = true;
    nix-direnv.enable = true;  # Intégration avec Nix flakes
  };

  # === TMUX ===
  programs.tmux = {
    enable = true;
    terminal = "tmux-256color";
    shell = "${pkgs.zsh}/bin/zsh";
    keyMode = "vi";
    baseIndex = 1;
    escapeTime = 0;
    historyLimit = 50000;
    mouse = true;
    extraConfig = ''
      # Split panes avec | et -
      bind | split-window -h -c "#{pane_current_path}"
      bind - split-window -v -c "#{pane_current_path}"

      # Navigation vim-like entre panes
      bind h select-pane -L
      bind j select-pane -D
      bind k select-pane -U
      bind l select-pane -R

      # Status bar
      set -g status-style bg=default,fg=white
      set -g status-left "#[fg=green]#S "
      set -g status-right "#[fg=yellow]%H:%M #[fg=cyan]%d-%m-%Y"
    '';
  };

  # === FZF ===
  programs.fzf = {
    enable = true;
    enableZshIntegration = true;
    defaultCommand = "fd --type f --hidden --follow --exclude .git";
    defaultOptions = [
      "--height 40%"
      "--layout=reverse"
      "--border"
      "--info=inline"
    ];
  };

  # === FICHIERS DE CONFIGURATION ARBITRAIRES ===
  home.file = {
    ".config/k9s/skin.yml".text = ''
      k9s:
        body:
          bgColor: default
          fgColor: white
    '';
  };

  # Laisser Home Manager gérer lui-même
  programs.home-manager.enable = true;
}
# Installer Home Manager (standalone, sans NixOS)
nix-channel --add https://github.com/nix-community/home-manager/archive/release-24.11.tar.gz home-manager
nix-channel --update
nix-shell '<home-manager>' -A install

# Ou avec les flakes (recommandé)
nix run home-manager/release-24.11 -- init --switch

# Appliquer la configuration
home-manager switch

# Lister les générations Home Manager
home-manager generations

# Rollback
home-manager generations  # noter le numéro
# Activer une génération précédente
/nix/var/nix/profiles/per-user/admin/home-manager-XX-link/activate

devenv.sh : Nix simplifié pour le développement

devenv.sh est un outil construit sur Nix qui simplifie radicalement la création d'environnements de développement. Si vous trouvez le langage Nix intimidant, devenv est votre porte d'entrée :

# devenv.nix — Configuration devenv pour un projet web
{ pkgs, lib, config, ... }:

{
  # Paquets disponibles dans l'environnement
  packages = [
    pkgs.git
    pkgs.jq
    pkgs.httpie
    pkgs.just
  ];

  # Langages avec gestion automatique des versions
  languages.python = {
    enable = true;
    version = "3.12";
    poetry = {
      enable = true;
      activate.enable = true;
    };
  };

  languages.javascript = {
    enable = true;
    package = pkgs.nodejs_22;
    pnpm.enable = true;
  };

  # Services locaux (démarrés avec `devenv up`)
  services.postgres = {
    enable = true;
    package = pkgs.postgresql_16;
    initialDatabases = [
      { name = "myapp_dev"; }
      { name = "myapp_test"; }
    ];
    listen_addresses = "127.0.0.1";
    port = 5432;
  };

  services.redis = {
    enable = true;
    port = 6379;
  };

  # Processus personnalisés (démarrés avec `devenv up`)
  processes = {
    api.exec = "uvicorn app.main:app --reload --port 8000";
    worker.exec = "celery -A app.tasks worker --loglevel=info";
    frontend.exec = "cd frontend && pnpm dev";
  };

  # Scripts personnalisés (disponibles comme commandes)
  scripts = {
    migrate.exec = "alembic upgrade head";
    seed.exec = "python scripts/seed_data.py";
    test.exec = "pytest -v --cov=app tests/";
    lint.exec = "ruff check . && mypy app/";
  };

  # Pre-commit hooks
  pre-commit.hooks = {
    ruff.enable = true;
    mypy.enable = true;
    nixfmt-rfc-style.enable = true;
    shellcheck.enable = true;
    commitizen.enable = true;
  };

  # Variables d'environnement
  env = {
    DATABASE_URL = "postgresql://localhost:5432/myapp_dev";
    REDIS_URL = "redis://localhost:6379";
    DEBUG = "true";
  };

  # Message d'entrée
  enterShell = ''
    echo "🔧 Environnement de développement prêt !"
    echo ""
    echo "Commandes disponibles :"
    echo "  devenv up     - Démarrer tous les services"
    echo "  migrate       - Appliquer les migrations"
    echo "  seed          - Peupler la base de données"
    echo "  test          - Lancer les tests"
    echo "  lint          - Vérifier le code"
  '';
}
# Installer devenv
nix profile install --accept-flake-config github:cachix/devenv/latest

# Initialiser dans un projet existant
devenv init

# Entrer dans l'environnement
devenv shell

# Démarrer tous les services (PostgreSQL, Redis, API, frontend...)
devenv up

# Lancer les tests (script personnalisé)
devenv shell -- test

# Mettre à jour les dépendances
devenv update

Cachix : le cache binaire

L'un des reproches fréquents à Nix est le temps de compilation. Quand un paquet n'est pas disponible en cache binaire, Nix le compile depuis les sources, ce qui peut prendre beaucoup de temps. Cachix résout ce problème en fournissant un service de cache binaire partagé :

# Installer Cachix
nix-env -iA cachix -f https://cachix.org/api/v1/install

# S'authentifier
cachix authtoken YOUR_TOKEN

# Créer un cache pour votre organisation
cachix create myorg

# Pousser les résultats de build vers le cache
nix build .#default | cachix push myorg

# Configurer Nix pour utiliser votre cache
# Dans /etc/nix/nix.conf ou configuration.nix :
# substituters = https://cache.nixos.org https://myorg.cachix.org
# trusted-public-keys = cache.nixos.org-1:... myorg.cachix.org-1:...

# Dans un flake, utiliser nixConfig pour configurer le cache
# (dans flake.nix)
# nixConfig = {
#   extra-substituters = [ "https://myorg.cachix.org" ];
#   extra-trusted-public-keys = [ "myorg.cachix.org-1:..." ];
# };

# Intégration CI : pousser automatiquement après chaque build
# GitHub Actions :
# - name: Push to Cachix
#   run: |
#     nix build .#default
#     cachix push myorg ./result

Images Docker depuis Nix

Nix peut construire des images Docker extrêmement optimisées, sans Docker lui-même, et sans les couches inutiles d'une image basée sur une distribution :

# Image Docker construite avec Nix
# Résultat : image minimale contenant UNIQUEMENT ce qui est nécessaire
{ pkgs ? import <nixpkgs> {} }:

pkgs.dockerTools.buildLayeredImage {
  name = "mon-api";
  tag = "latest";

  # Contenu de l'image (uniquement les paquets nécessaires)
  contents = [
    pkgs.python312
    pkgs.python312Packages.fastapi
    pkgs.python312Packages.uvicorn
    pkgs.cacert  # Certificats SSL
    pkgs.busybox  # Utilitaires de base (optionnel, pour le debug)
  ];

  # Configuration de l'image
  config = {
    Cmd = [ "uvicorn" "app.main:app" "--host" "0.0.0.0" "--port" "8000" ];
    ExposedPorts = { "8000/tcp" = {}; };
    Env = [
      "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
      "PYTHONUNBUFFERED=1"
    ];
    WorkingDir = "/app";
  };

  # Copier le code source de l'application
  extraCommands = ''
    mkdir -p app
    cp -r ${./src}/* app/
  '';
}
# Construire l'image
nix build -f docker.nix
# Le résultat est un fichier tar
ls -lh result
# -r--r--r-- 1 root root 85M result  (vs ~500MB pour une image Python classique !)

# Charger l'image dans Docker
docker load < result

# Vérifier
docker images mon-api
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# mon-api      latest    abc123def456   53 years ago   85MB
# Note : "53 years ago" = timestamp 0 pour la reproductibilité

# Lancer
docker run -p 8000:8000 mon-api

Les avantages des images Docker construites avec Nix :

  • Taille minimale : seuls les paquets nécessaires sont inclus (pas de gestionnaire de paquets, pas de shell inutile, pas de man pages)
  • Reproductibilité : le même flake.lock = la même image, bit pour bit
  • Sécurité : surface d'attaque réduite (pas de coreutils inutiles, pas de shell par défaut)
  • Pas besoin de Docker pour construire : Nix construit l'image sans daemon Docker
  • Couches optimisées : buildLayeredImage crée des couches intelligentes pour maximiser la réutilisation du cache

Déploiement avec NixOS

Plusieurs outils permettent de déployer des configurations NixOS sur des machines distantes :

deploy-rs

deploy-rs est l'outil de déploiement le plus populaire pour NixOS. Il est simple, rapide, et supporte le rollback automatique :

# flake.nix avec deploy-rs
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    deploy-rs.url = "github:serokell/deploy-rs";
  };

  outputs = { self, nixpkgs, deploy-rs }: {
    # Configuration NixOS pour chaque serveur
    nixosConfigurations = {
      web-1 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./hosts/web-1/configuration.nix ];
      };
      web-2 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./hosts/web-2/configuration.nix ];
      };
      db-1 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./hosts/db-1/configuration.nix ];
      };
    };

    # Configuration de déploiement
    deploy.nodes = {
      web-1 = {
        hostname = "10.0.0.10";
        profiles.system = {
          user = "root";
          sshUser = "deploy";
          path = deploy-rs.lib.x86_64-linux.activate.nixos
            self.nixosConfigurations.web-1;
          # Rollback automatique si le serveur ne répond plus après 60s
          autoRollback = true;
          magicRollback = true;
        };
      };
      web-2 = {
        hostname = "10.0.0.11";
        profiles.system = {
          user = "root";
          sshUser = "deploy";
          path = deploy-rs.lib.x86_64-linux.activate.nixos
            self.nixosConfigurations.web-2;
          autoRollback = true;
          magicRollback = true;
        };
      };
      db-1 = {
        hostname = "10.0.0.20";
        profiles.system = {
          user = "root";
          sshUser = "deploy";
          path = deploy-rs.lib.x86_64-linux.activate.nixos
            self.nixosConfigurations.db-1;
          autoRollback = true;
          magicRollback = true;
        };
      };
    };

    # Vérifications
    checks = builtins.mapAttrs
      (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib;
  };
}
# Déployer tous les serveurs
nix run github:serokell/deploy-rs -- .

# Déployer un serveur spécifique
nix run github:serokell/deploy-rs -- .#web-1

# Déployer avec dry-run
nix run github:serokell/deploy-rs -- . -- --dry-activate

# Le magic rollback fonctionne ainsi :
# 1. deploy-rs active la nouvelle configuration
# 2. Un timer de 60 secondes démarre
# 3. Si le déploiement réussit (confirmé via SSH), le timer est annulé
# 4. Si le serveur est inaccessible, le timer expire et le rollback est effectué

Colmena

Colmena est une alternative à deploy-rs, inspirée de NixOps mais plus moderne et plus simple :

# Déployer avec Colmena
colmena apply

# Déployer un nœud spécifique
colmena apply --on web-1

# Build sans déployer
colmena build

# Exécuter une commande sur tous les nœuds
colmena exec -- systemctl status nginx

Comparaison avec les alternatives

Nix vs Docker

Nix et Docker résolvent des problèmes différents mais complémentaires :

Aspect Nix Docker
Objectif principal Reproductibilité des builds et environnements Isolation et portabilité des applications
Granularité Paquet par paquet Conteneur entier (image)
Reproductibilité Bit-à-bit (avec flake.lock) Approximative (même Dockerfile peut produire des images différentes)
Dev environment Natif (nix develop, devenv) Nécessite des montages volumes, rebuild d'images
Performance dev Natif (pas de couche VM/conteneur) Overhead I/O (surtout sur macOS)
Déploiement prod NixOS ou images Docker construites par Nix Standard de l'industrie
Courbe d'apprentissage Raide (langage Nix) Modérée (Dockerfile simple)

En pratique, beaucoup d'équipes utilisent Nix ET Docker ensemble : Nix pour construire des images Docker reproductibles et pour les environnements de développement, Docker/Kubernetes pour le déploiement en production.

Nix vs Ansible

Aspect Nix/NixOS Ansible
Paradigme Déclaratif pur Impératif avec déclaration d'état souhaité
Reproductibilité Garantie (même entrées = même résultat) Best-effort (dépend de l'état initial)
Rollback Atomique et instantané Pas natif (il faut écrire des playbooks de rollback)
Idempotence Garantie par construction Responsabilité du développeur de playbooks
Systèmes cibles NixOS uniquement (ou Nix sur d'autres distros) N'importe quel Linux (et Windows, macOS, network devices)
Adoption Communauté en croissance Standard de l'industrie, très large adoption

Nix vs Guix

GNU Guix est un projet similaire à Nix, basé sur les mêmes principes (gestionnaire de paquets fonctionnel, reproductibilité), mais avec des différences notables :

  • Langage : Guix utilise Guile Scheme (un vrai langage de programmation) au lieu du langage Nix custom
  • Philosophie : Guix est un projet GNU, strictement libre (pas de paquets non-libres par défaut)
  • Taille : Nixpkgs (~100k paquets) est significativement plus grand que Guix (~30k paquets)
  • Communauté : Nix a une communauté plus large et une adoption industrielle plus importante
  • Écosystème : Nix a plus d'outils tiers (Home Manager, devenv, Cachix, deploy-rs, etc.)

Courbe d'apprentissage et conseils

Soyons honnêtes : la courbe d'apprentissage de Nix est raide. Le langage Nix est un langage fonctionnel lazy-evaluated avec une syntaxe unique, la documentation est parfois fragmentée, et les messages d'erreur peuvent être cryptiques. Voici comment aborder l'apprentissage :

Phase 1 : Utilisateur (semaine 1-2)

  1. Installez Nix (pas NixOS, juste le gestionnaire de paquets) sur votre distribution actuelle
  2. Utilisez nix shell pour tester des outils sans les installer (nix shell nixpkgs#ripgrep)
  3. Utilisez nix run pour exécuter des programmes (nix run nixpkgs#btop)
  4. Essayez devenv.sh sur un projet existant — c'est la porte d'entrée la plus accessible

Phase 2 : Développeur (semaine 3-6)

  1. Apprenez les bases du langage Nix : nix.dev est la meilleure ressource pour débuter
  2. Créez un flake.nix pour un de vos projets (utilisez les templates : nix flake init -t templates#trivial)
  3. Configurez direnv + nix-direnv pour activer automatiquement l'environnement Nix en entrant dans un répertoire
  4. Explorez Nixpkgs : search.nixos.org pour chercher des paquets et des options NixOS

Phase 3 : Avancé (mois 2-6)

  1. Essayez NixOS dans une VM d'abord, puis sur une machine secondaire
  2. Configurez Home Manager pour gérer vos dotfiles
  3. Construisez des images Docker avec Nix
  4. Écrivez vos propres derivations pour packager vos applications
  5. Configurez Cachix pour partager les builds avec votre équipe

Ressources d'apprentissage recommandées

  • nix.dev : la documentation officielle réécrite, moderne et bien structurée
  • zero-to-nix.com : tutorial interactif pour les débutants (par Determinate Systems)
  • nixos.wiki : wiki communautaire avec des exemples pratiques
  • Nix Pills : série d'articles approfondis sur le fonctionnement interne de Nix
  • search.nixos.org : moteur de recherche pour les paquets et les options NixOS
  • NixOS Discourse : forum communautaire actif et accueillant

Quand adopter Nix ?

Nix n'est pas pour tout le monde ni pour tous les contextes. Voici des critères pour décider :

Adoptez Nix si :

  • Vous avez des problèmes récurrents de reproductibilité (« ça marche sur ma machine »)
  • Votre projet utilise plusieurs langages/runtimes et la gestion des versions est un cauchemar
  • Vous voulez des environnements de développement identiques pour toute l'équipe
  • Vous construisez des images Docker et voulez une reproductibilité parfaite
  • Vous gérez des serveurs et voulez des rollbacks atomiques
  • Vous êtes prêt à investir du temps d'apprentissage pour des bénéfices à long terme
  • Votre équipe est à l'aise avec la programmation fonctionnelle

Peut-être pas encore Nix si :

  • Votre projet est simple avec peu de dépendances
  • Votre équipe n'a pas le temps d'investir dans l'apprentissage
  • Vous avez besoin de support commercial (bien que Determinate Systems propose du support)
  • Votre infrastructure est principalement Windows
  • Vous êtes satisfait de Docker + Ansible pour vos besoins actuels

L'écosystème Nix en 2025-2026

L'écosystème Nix est en pleine effervescence :

  • Determinate Systems : entreprise fondée par des contributeurs majeurs de Nix, proposant des outils commerciaux (FlakeHub, Determinate Nix Installer) et du support entreprise
  • Flox : outil qui simplifie l'utilisation de Nix pour les équipes de développement, avec une interface familière
  • Tvix : réécriture de l'évaluateur Nix en Rust, pour de meilleures performances et un meilleur support des erreurs
  • Lix : fork communautaire de Nix focalisé sur la stabilité et la gouvernance ouverte
  • NixOS Foundation : restructuration de la gouvernance pour une meilleure représentation de la communauté
  • Adoption croissante : de plus en plus d'entreprises (Shopify, Replit, Determinate Systems, Flox, Cachix, Hercules CI) utilisent et contribuent à Nix
  • Intégration GitHub : les GitHub Codespaces et Actions supportent de mieux en mieux Nix

Direnv + Nix : l'expérience développeur optimale

La combinaison de direnv et nix-direnv crée une expérience développeur exceptionnelle : quand vous entrez dans un répertoire contenant un flake.nix, l'environnement de développement est automatiquement activé :

# Installer direnv et nix-direnv
nix profile install nixpkgs#direnv nixpkgs#nix-direnv

# Ajouter à votre .zshrc ou .bashrc
eval "$(direnv hook zsh)"

# Dans votre projet, créer un .envrc
echo "use flake" > .envrc
direnv allow

# Maintenant, chaque fois que vous entrez dans le répertoire :
cd mon-projet/
# direnv: loading .envrc
# direnv: using flake
# (tous les outils de votre flake.nix sont disponibles)

python3 --version  # La version définie dans flake.nix
node --version     # La version définie dans flake.nix

cd ..
# direnv: unloading
python3 --version  # La version système (ou "command not found")

Le cache de nix-direnv fait que les activations suivantes sont instantanées (pas de rebuild). C'est la meilleure façon d'utiliser Nix au quotidien pour le développement.

Conclusion

Nix et NixOS représentent un changement de paradigme dans la gestion des logiciels et des systèmes. En appliquant les principes de la programmation fonctionnelle — pureté, immutabilité, composition — à la gestion de paquets et à la configuration système, ils résolvent des problèmes fondamentaux que les outils traditionnels ne peuvent qu'atténuer.

Les bénéfices concrets sont considérables :

  • Reproductibilité garantie : même flake.lock = même environnement, sur n'importe quelle machine
  • Fin du « ça marche sur ma machine » : chaque développeur a exactement le même environnement
  • Rollbacks atomiques : une mise à jour qui casse le système ? Un rollback instantané restaure l'état précédent
  • Coexistence de versions : Python 3.10 et 3.12, Node 20 et 22, sur la même machine, sans conflit
  • Images Docker minimales : construites par Nix, reproductibles, et une fraction de la taille des images classiques
  • Infrastructure as Code véritablement déclaratif : NixOS décrit l'état souhaité, pas les étapes pour y arriver

La courbe d'apprentissage est réelle, mais l'investissement est rentable. Commencez par installer Nix sur votre machine actuelle (sans passer à NixOS), utilisez nix shell et nix develop pour vos projets, et explorez devenv.sh pour une introduction en douceur. Une fois que vous aurez goûté à la reproductibilité de Nix, il sera difficile de revenir en arrière.

En 2025-2026, avec la maturation des flakes, la croissance de Nixpkgs, les outils comme devenv et Home Manager, et l'investissement croissant de l'industrie, Nix n'est plus un outil de niche pour les passionnés. C'est une technologie de production, utilisée par des entreprises à travers le monde pour construire des systèmes fiables et reproductibles.

Pour aller plus loin : commencez par zero-to-nix.com pour une introduction interactive, puis explorez nix.dev pour la documentation approfondie. Le moteur de recherche NixOS est votre meilleur ami pour trouver des paquets et des options de configuration. Et rejoignez la communauté sur le NixOS Discourse — elle est accueillante et passionnée.
Vous vous êtes abonné avec succès à CodeClan
Parfait ! Ensuite, complétez le paiement pour obtenir un accès complet à tout le contenu premium.
Erreur ! Impossible de s'inscrire. Lien invalide.
Bienvenue ! Vous vous êtes connecté avec succès.
Erreur ! Impossible de se connecter. Veuillez réessayer.
Succès ! Votre compte est entièrement activé, vous avez maintenant accès à tout le contenu.
Erreur ! Le paiement Stripe a échoué.
Succès ! Vos informations de facturation sont mises à jour.
Erreur ! La mise à jour des informations de facturation a échoué.