Blog

Paketverwaltung mit Nix

Matthisk Heimensen

Aktualisiert Oktober 21, 2025
7 Minuten

Als Softwareentwickler verwenden wir täglich Paketmanager. Wir verwenden sie, um Abhängigkeiten zu installieren, die wir zum Ausführen und Erstellen der von uns geschriebenen Software benötigen. Wahrscheinlich kann jeder Software-Ingenieur die Frustration nachvollziehen, die irgendwann bei der Verwendung dieser Paketmanager auftritt. Manchmal funktionieren Pakete, die auf dem Rechner Ihres Kollegen einwandfrei zu funktionieren scheinen, auf Ihrem nicht. Auch wenn sich die Paketmanager im Laufe der Zeit erheblich verbessert haben, treten solche Probleme immer noch auf. Vielleicht gibt es einen grundlegenden Designfehler in der Art und Weise, wie wir an die Paketverwaltung herangehen. Es gibt einen Paketmanager, der versucht, die Dinge anders anzugehen, und er heißt Nix. Lassen Sie uns einen Blick darauf werfen, was Nix ist und wie Sie es heute auf Ihrem Rechner verwenden können.

Geben Sie die Nix ein

Nix ist vieles: eine Sprache, ein Betriebssystem (nixos), ein Verteilungssystem und ein System zur kontinuierlichen Integration (Hydra). Aber im Kern ist es ein Paketmanager, und zwar ein Paketmanager, der von Grund auf darauf ausgelegt ist, rein und unveränderlich zu sein. Rein in dem Sinne, dass die Erstellung eines Pakets keine unkontrollierten Nebeneffekte haben kann, und unveränderlich in dem Sinne, dass kein globaler Paketstatus an Ort und Stelle verändert wird. Dies ist ein grundlegender Unterschied zur derzeitigen Vorgehensweise bei der Installation von Paketen, bei der wir alle Binärdateien in ein globales und veränderbares Verzeichnis installieren, z.B. /usr/local/bin. Diese Änderung ermöglicht es uns, verschiedene Versionen derselben ausführbaren Datei oder Bibliothek auf unserem Betriebssystem zu unterstützen.

Nix ist rein, d.h. es kann dasselbe Paket mit unterschiedlichen Eingabeparametern erstellen. Es erfasst alle Eingabeparameter, die von der Version des GCC bis hin zu den Bibliotheksabhängigkeiten (z.B. glibc) reichen können. In Nix wird ein gebündeltes Paket also nicht nur durch seinen Namen und seine Version referenziert, sondern es wird ihm die Aggregation aller Parameter vorangestellt, die zur Erstellung dieses Pakets verwendet wurden. Diese Aggregation wird als Hash dargestellt. Wenn sich also einer der Eingabeparameter ändert, ändert sich auch dieser Hash.

Binärdateien über diese Hashes zu referenzieren, wäre wirklich unproduktiv, denn wir wollen in unserem Terminal git und nicht 86b4f4cd27e63c8e05c745807dd281ec04c38521-git eingeben können. Nix löst dieses Problem, indem es einen Symlink unter dem Namen git innerhalb eines Verzeichnisses auf Ihrer PATH zum tatsächlichen Speicherort der Git-Binärdatei im Nix-Speicher erstellt. Eine Sammlung solcher Symlinks wird als Profil bezeichnet.

Symlinks ermöglichen Unveränderlichkeit. Denn wir müssen die Binärdateien nicht mehr direkt in den Verzeichnissen auf PATH (z.B. /usr/local/bin) ändern, sondern verlassen uns auf das Verzeichnis /nix/store. Und atomare Operationen, denn die Erstellung von Symlinks erfolgt als letzter Schritt in unserem Installationsverfahren. Eine Installation, die auf halbem Weg scheitert, hat also keine spürbaren Nebenwirkungen.

Tutorial

In diesem Tutorial erkläre ich, wie Sie Nix verwenden können, um Binärdateien zu installieren und isolierte und reproduzierbare Entwicklungsumgebungen zu schaffen. Es handelt sich keineswegs um eine vollständige Anleitung für die Verwendung von Nix. Aber ich hoffe, dass es Ihre Vorstellungskraft von den Möglichkeiten von Nix anregt.Installieren Sie den Nix-Paketmanager:$ curl https://nixos.org/nix/install | shNach der Installation stehen uns einige neue Befehle zur Verfügung:

  • nix-env zum Installieren von Abhängigkeiten und Ändern Ihres aktuellen Profils
  • nix-shell wird verwendet, um Shells zu starten, die auf Nix-Ausdrücken basieren
  • nix-store zum Abfragen oder Manipulieren des Nix-Speicher

Und es wurde ein Verzeichnis für den Nix-Store unter /nix erstellt. Dieses Verzeichnis enthält alle installierten Pakete, Profile und Konfigurationen. Ihre globale Umgebung wird nur durch Symlinks in den Nix-Store verändert. Wir können nun verschiedene Aktionen zum Suchen, Installieren und Deinstallieren von Paketen ausführen:

Suchen Sie nach Paketen, die mit nodejs beginnen in dem entfernten Repository

$ nix-env -qaP 'nodejs.*'

Installieren Sie Node 12 in Ihrem Profil

$ nix-env -iA nixpkgs.nodejs-12_x

Die Ausführung dieses Befehls zeigt an, dass die Binärdatei von node in einem Verzeichnis namens .nix-profile zu finden ist. Wenn Sie den Symlinks in diesem Verzeichnis folgen, landen Sie bei einer Binärdatei im Nix-Store irgendwo in /nix/store.

$ which node

Sie können das Verzeichnis /nix/store einsehen, um alle Abhängigkeiten zu sehen, die derzeit auf Ihrem Rechner installiert sind. Sie werden sehen, dass allen Paketen eine Raute vorangestellt ist, die, wie im ersten Abschnitt erwähnt, alle Eingabeparameter darstellt, die zur Erstellung dieses Pakets verwendet werden.

Wenn wir eine zweite Version von Node installieren, würde diese den Symlink in unserem Nix-Profil überschreiben.

$ nix-env -iA nixpkgs.nodejs-11_x

Wenn Sie node --version ausführen, wird Ihnen mitgeteilt, dass node an Version 11 gebunden ist.

$ node --version

Da die Binärdatei von node ein Symlink auf die tatsächliche Binärdatei ist, die im Nix-Store (unter /nix) gespeichert ist, können wir auch eine isolierte Shell laden, die node auf eine bestimmte Version von node im Nix-Store zeigt.

Starten Sie eine neue Shell, in der nodejs12 verfügbar ist. Sobald Sie die Shell verlassen, befindet sich nodejs-12 nicht mehr in Ihrem Pfad.

$ nix-shell -p nodejs-12_x

Mit der Sprache Nix ist es auch möglich, eine Konfigurationsdatei zu schreiben, die wir wiederverwenden können. Diese Konfigurationsdateien werden Ableitungen genannt und sind der wichtigste Baustein von Nix. Sie beschreiben, wie Pakete gebaut werden sollen und mit welchen Parametern. Sie sind in der Nix-Sprache geschrieben. Nehmen Sie zum Beispiel diese Ableitung, die nodejs v12 in die Umgebung lädt:

with import <nixpkgs> {};
stdenv.mkDerivation {
  name = "node-environment";
  buildInputs = [
    pkgs.nodejs-12_x
  ];
}

Wenn Sie mehr über das Schreiben von Nix-Ableitungen erfahren möchten, lesen Sie die Nix-Pille zu Schreiben von Ableitungen

Wenn wir diese Datei als default.nix speichern, können wir sie innerhalb einer Nix-Shell mit dem folgenden Befehl laden:

$ nix-shell default.nix

Wir können nun reproduzierbare Entwicklungsumgebungen erstellen, indem wir eine Nix-Ableitung schreiben. Um die Umgebung zu betreten, benötigen wir immer noch einen Aufruf von nix-shell, wir könnten aber auch ein Tool namens direnv verwenden, um die Nix-Ableitung automatisch zu laden, während wir das Verzeichnis mit unserer default.nix-Ableitung betreten.

Bonus: im Tandem mit direnv

direnv ist ein Werkzeug zur Umgebungsverwaltung, das von zimbatm entwickelt wurde. Es setzt und entfernt im Wesentlichen Umgebungsvariablen in der Shell in Abhängigkeit vom aktuellen Verzeichnis und dem Vorhandensein einer .envrc-Datei.

Before each prompt, direnv checks for the existence of a .envrc file in the current and parent directories. If the file exists (and is authorized), it is loaded into a bash sub-shell and all exported variables are then captured by direnv and then made available to the current shell.

Da direnv von Haus aus Nix unterstützt, müssen wir nur eine .envrc erstellen und die Nix-Integration aktivieren. Führen Sie dazu den folgenden Befehl in dem Verzeichnis aus, in dem sich Ihre default.nix-Datei befindet:

$ direnv edit .

Fügen Sie die folgende Zeile in die Datei ein, um die Nix-Integration zu aktivieren, und speichern Sie:

use nix

Sobald die Datei gespeichert ist, lädt direnv automatisch die Umgebung neu. Wir sollten etwas in dieser Art sehen:

direnv: loading .envrc
direnv: using nix
direnv: export +AR +AS +CC +CMAKE_OSX_ARCHITECTURES +CONFIG_SHELL +CXX +HOST_PATH +IN_NIX_SHELL +LD +LD_DYLD_PATH +MACOSX_DEPLOYMENT_TARGET +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_x86_64_apple_darwin_TARGET_HOST +NIX_BUILD_CORES +NIX_BUILD_DONT_SET_RPATH +NIX_BUILD_TOP +NIX_CC +NIX_CC_WRAPPER_x86_64_apple_darwin_TARGET_HOST +NIX_CFLAGS_COMPILE +NIX_COREFOUNDATION_RPATH +NIX_CXXSTDLIB_COMPILE +NIX_CXXSTDLIB_LINK +NIX_DONT_SET_RPATH +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_IGNORE_LD_THROUGH_GCC +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_NO_SELF_RPATH +NIX_STORE +NM +NODE_PATH +PATH_LOCALE +RANLIB +SDKROOT +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +TEMP +TEMPDIR +TMP +__darwinAllowLocalNetworking +__impureHostDeps +__propagatedImpureHostDeps +__propagatedSandboxProfile +__sandboxProfile +buildInputs +builder +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +gl_cv_func_getcwd_abort_bug +name +nativeBuildInputs +out +outputs +patches +propagatedBuildInputs +propagatedNativeBuildInputs +shell +stdenv +strictDeps +system ~PATH

Wenn wir which node ausführen, sollten wir sehen, dass node jetzt aus dem Nix-Store geladen wird:

/nix/store/9pfsxwkr43907dp7spwidpr3hjbz0v5w-nodejs-12.5.0/bin/node

Fazit

Die Verwaltung mehrerer Binärversionen oder reproduzierbarer Build-Umgebungen ist nur der Anfang der Möglichkeiten von nix. Es kann zur Verwaltung vollständig reproduzierbarer Betriebssysteme oder zur Erstellung reproduzierbarer Container-Images verwendet werden. Nix ist potenziell ein großartiges Werkzeug für die Verwaltung reproduzierbarer Entwicklungsumgebungen. Auch wenn das Tooling aus Sicht der Benutzerfreundlichkeit noch etwas holprig ist und die Unterstützung der Paketregistrierung unter OS X besser sein könnte. Die Philosophie von Nix birgt großes Potenzial für die zukünftigen Versionen des Betriebssystems und des Paketmanagers.

Vorbehalte

  • Nix wird nur unter Linux und Mac OS unterstützt, und derzeit ist die Ableitungsunterstützung für Linux besser als die von Mac OS.
  • Da der Nix-Store unveränderlich ist, ist es nicht möglich, globale Abhängigkeiten Ihrer Programmiersprachen-Paketverwaltung innerhalb des Nix-Stores zu installieren. Da dies genau das ist, was npm versucht, wenn Sie npm install -g ausführen, wird dieser Vorgang fehlschlagen. Der folgende Blog-Beitrag beschreibt einen Weg, wie Sie dieses Problem umgehen können: nix-npm-install

Zusätzliches Material

Verfasst von

Matthisk Heimensen

A hands-on engineering consultant developing software across the stack. Helping teams deliver more predictably with more fun.

Contact

Let’s discuss how we can support your journey.