Nix Developer Shells · Workshop Lektion 8 / Flakes & mkShell

Lock-Files

Aus „funktioniert bei mir" wird „funktioniert überall" – die flake.lock.

Warum das zählt
Das ist die Zutat, die deine Mission ausdrücklich nennt. Ohne Lock-File ist „nixpkgs-unstable" jeden Tag etwas anderes. Die flake.lock nagelt jeden Input auf einen exakten Commit – und macht deine Dev-Shell echt reproduzierbar, heute wie in zwei Jahren.

Was die flake.lock festhält

In Lektion 5 hast du nixpkgs.url = "…nixos-unstable" geschrieben – ein beweglicher Zeiger. Beim ersten Flake-Befehl hat Nix automatisch eine flake.lock erzeugt, die diesen Zeiger auf einen konkreten Commit-Hash auflöst:

# flake.lock (gekürzt) – JSON, von Nix verwaltet:
"nixpkgs": {
  "locked": {
    "type": "github",
    "owner": "NixOS",
    "repo": "nixpkgs",
    "rev": "a1b2c3d…",        # ← exakter Commit
    "narHash": "sha256-…"      # ← Inhalts-Prüfsumme
  }
}

Solange diese Datei unverändert bleibt, bekommt jede:r exakt dasselbe Nixpkgs – also exakt dieselben Tool-Versionen in der Dev-Shell.

Die wichtigste Regel flake.lock gehört ins Git-Repo. Committe sie immer. Sie ist das, was Reproduzierbarkeit von einem Versprechen zu einer Garantie macht – das Pendant zu package-lock.json oder Cargo.lock.

Lock-Files steuern

$ nix flake lock          # erzeugt/ergänzt die lock-Datei, ohne zu aktualisieren
$ nix flake update        # aktualisiert ALLE Inputs auf den neuesten Stand
$ nix flake update nixpkgs # aktualisiert nur diesen einen Input
$ nix flake metadata      # zeigt die aktuell gepinnten Revisionen

Wichtig: Ein Update ist eine bewusste Entscheidung, die die flake.lock ändert. Danach läufst du auf neuen Versionen – also testen und den Lock-Diff committen, genau wie ein Dependency-Update in jedem anderen Ökosystem.

Versionen gezielt festhalten

Willst du bewusst auf einem stabilen Stand bleiben, zeig den Input auf einen Release-Branch statt auf unstable:

  inputs = {
    # stabiler Release-Zweig statt rollendem unstable:
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
  };

Der Branch in der url bestimmt die grobe Linie; die flake.lock pinnt darin den exakten Commit. Beides zusammen gibt dir „stabil und exakt".

Inputs zusammenführen mit follows

Hat dein Flake mehrere Inputs, die ihrerseits Nixpkgs brauchen, willst du ein gemeinsames Nixpkgs – sonst lädst du es doppelt. Das regelt follows:

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    flake-utils.url = "github:numtide/flake-utils";
    some-tool = {
      url = "github:foo/some-tool";
      inputs.nixpkgs.follows = "nixpkgs";   # nutzt unser nixpkgs
    };
  };
Dein Win Deine toolbox ist jetzt vollständig reproduzierbar: Wer sie klont und nix develop tippt, bekommt bit-genau deine Umgebung. Das ist das zentrale Versprechen von Nix – und ab hier hältst du es ein.

Besonderheiten & Stolperfallen

flake.lock nicht ignorieren Sie versehentlich in .gitignore zu packen, zerstört die Reproduzierbarkeit lautlos – plötzlich bekommt jede:r ein anderes Nixpkgs. Sie muss eingecheckt sein.
nix flake update ist kein No-Op Es kann jedes Tool in deiner Shell auf eine neue Version heben. Führ es bewusst aus, prüf danach, ob alles läuft, und committe den Lock-Diff als eigene Änderung – nicht beiläufig.
Update vs. ändern der url Die url ändern (z. B. von unstable auf 24.11) ist eine andere Aktion als nix flake update. Erstere wechselt die Linie, Letztere holt den neuesten Commit der bestehenden Linie.

Kurz prüfen (aus dem Kopf)

Nicht spicken – Abrufen aus dem Gedächtnis ist genau die Übung, die hängen bleibt.

Was genau hält die flake.lock fest?

Was tut nix flake update?

Was passiert, wenn die flake.lock nicht eingecheckt ist?

Übung für Teilnehmende

Ziel: Den gepinnten Stand sehen, ein Update bewusst durchführen und den Diff verstehen.

  1. nix flake metadata – notiere die aktuelle nixpkgs-Revision.
  2. Führe nix flake update aus und schau dir git diff flake.lock an.
  3. Prüfe mit nix develop + go version, ob sich eine Version verändert hat.
  4. Bonus: Ändere die url auf nixos-24.11 und vergleiche das Verhalten.

Tipp: Mach das Update in einem eigenen Commit – so kannst du es jederzeit zurückrollen.

Lösung anzeigen
$ nix flake metadata | grep -i nixpkgs
$ nix flake update
# warning: updating lock file …: 'nixpkgs' … → …
$ git diff flake.lock        # nur rev + narHash ändern sich
$ git add flake.lock && git commit -m "chore: nixpkgs aktualisiert"

Genau dieser Workflow – Update, testen, Lock committen – ist Dependency-Management in Nix.

Primärquelle zum Lesen NixOS Wiki – Flakes: lock file. Erklärt Aufbau und Pflege der flake.lock sowie follows kompakt und korrekt.
Ich bin dein Teacher. Unklar, wie du auf einen ganz bestimmten alten Commit pinnst, oder wie zwei Flakes dasselbe Nixpkgs teilen? Frag im Chat – ich zeig dir das passende follows.
← Lektion 7 · mkShell II Lektion 9 · Eigene Pakete I →
Als Nächstes: Lektion 9 – Eigene Pakete I (stdenv.mkDerivation, Build-Phasen)