Immutable-Linux mit dem Paketmanager Nix NixOS – Die Eleganz der Simplizität

Von Filipe Pereira Martins & Anna Kobylinska 8 min Lesedauer

NixOS, eine Linux-Distribution der NixOS Foundation, will mit ihrer deklarativen Konfiguration und ihrem innovativen Stack die Softwareverwaltung revolutionieren. Das Aufkommen generativer KI weckt neues Interesse an dem deklarativen Ansatz.

Nach rund 20 Jahren des Projektbestehens ist es soweit: Die erste #NixCon Nordamerika wird am 14. und 15. März 2024 in Pasadena, Kalifornien, stattfinden.
Nach rund 20 Jahren des Projektbestehens ist es soweit: Die erste #NixCon Nordamerika wird am 14. und 15. März 2024 in Pasadena, Kalifornien, stattfinden.
(Bild: Nixos.org)

In engen Fachkreisen anerkannt und doch größtenteils unbekannt, gilt NixOS unter den Eingeweihten als ein Geheimtipp für den Betrieb von Immutable Infrastructure. Die Entwicklung des Nix-Ökosystems läuft bereits seit dem Jahre 2003 – und zwar unverändert auf Hochtouren.

Diese bemerkenswerte Kontinuität verdankt die quelloffene Linux-Distribution der Förderung durch namhafte Unternehmen wie Equinix Metal, GitHub, Hetzner Online und Fastly. Auch renommierte akademische Einrichtungen, darunter die Universität Utrecht, haben zu dem Projekt beigetragen.

Was NixOS so einzigartig macht, ist die deklarative Herangehensweise in Bezug auf die Konfiguration in Verbindung mit atomaren Updates. NixOS garantiert die exakte Reproduzierbarkeit einer Systemumgebung auf anderen physischen Systemen und eine einfache Wiederherstellung von stabilen Systemzuständen (etwa nach einem fehlerhaften Update).

Ersteres ist nützlich für die Bereitstellung identischer Entwicklungsumgebungen auf verschiedenen Maschinen; letzteres stellt eine Voraussetzung für die Verfügbarkeit einer Bereitstellung dar. NixOps überträgt das Konzept auf CloudOps. Das Kernstück des Systems bildet in beiden Fällen der Paketmanager Nix.

Vom deklarativen Paketmanager zu NixOS

Den Nix-Paketmanager hatte bekanntlich Eelco Dolstra als Teil seiner Doktorarbeit entwickelt. Den ersten Prototyp von NixOS schuf Armijn Hemel für seine Masterarbeit.

Der frisch promovierte Dolstra durfte dann in seiner Postdoktorandenzeit innerhalb des TraCE-Projekts (finanziert von NIRICT, dem Niederländischen Institut für Forschung in der Informations- und Kommunikationstechnologie, und LaQuSo, Laboratory for Quality Software) weiter an NixOS feilen und wirkte dabei an Hydra mit, dem kontinuierlichen Build-System auf dem Unterbau von Nix.

So entstand die erste Linux-Distribution mit Fähigkeiten zur deklarativen Systemverwaltung. Rund um diese Lösungen kam dann das Nix-Ökosystem auf. Es ist eine Sammlung von Technologien für Linux und Darwin (Apples quelloffenen Unterbau für das proprietäre Betriebssystem macOS), mit der sich Systeme und Softwarepakete samt deren Abhängigkeiten reproduzierbar bauen sowie deklarativ konfigurieren und verwalten lassen.

Zum Erfassen der Spezifikationen für die Erstellung und Verwaltung von reproduzierbaren Builds macht sich das Ökosystem eine speziell dafür entwickelte domänenspezifische Sprache namens Nix zu Nutze. Sie ist dynamisch (also kontextbedingt anpassungsfähig), funktional (das funktionale Programmierparadigma bevorzugt die Verwendung von Funktionen und vermeidet veränderliche Zustände) und träge (engl. lazy; sie führt Berechnungen nur dann aus, wenn die Ergebnisse abgerufen werden).

All diese Eigenschaften machen Nix zu einem leistungsfähigen Werkzeug für die Spezifikation und Verwaltung von reproduzierbaren Builds. Nix verwendet deklarative Ausdrücke, um den Zustand von Systemen und Paketen zu definieren. Die Sprache beschreibt das gewünschte Ergebnis statt einer Reihe von Anweisungen – nach dem Vorbild anderer funktionaler Sprachen. Alles, bis hin zum Kernel, wird mit dieser deklarativen Build-Sprache erstellt.

Der gleichnamige Paketmanager analysiert die Nix-Ausdrücke und legt das Ergebnis in einer Speicheradresse mit einem Hash des Abhängigkeitsbaums ab. Dies ist ein zentrales Merkmal von Nix und eine Voraussetzung für die Reproduzierbarkeit von Builds.

Dieser Ansatz erlaubt es dem System, Probleme mit Abhängigkeiten erst gar nicht aufkommen zu lassen. Es ermöglicht die konfliktfreie Handhabung mehrerer Versionen samt der Unterstützung für saubere Rollbacks.

Hydra, das Continuous-Integration-System, das eng mit Nix und NixOS verbunden ist, verwendet die Nix-Sprache, um Build-Jobs und deren Abhängigkeiten zu beschreiben. Das automatisierte System überprüft kontinuierlich oder periodisch den Quellcode eines Projekts, baut ihn, führt Tests durch und erstellt Berichte für die Developer. Auf diese Weise lassen sich Fehler automatisch und damit frühzeitig erkennen.

Nix behandelt jede Änderung als einen neuen, unabhängigen Zustand, was das Systemmanagement robuster und vorhersehbarer macht. Es verschiebt das funktionale Paradigma de facto vom Anwendungs- in den Systembereich. Die Vorteile dieser Herangehensweise sollten erst viele Jahre später mit dem Aufkommen der Containerisierung und Kubernetes zum Vorschein treten.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

Dank seiner einzigartigen Eigenschaften hat sich NixOS im Laufe seines Bestehens in einer Reihe von Anwendungsfällen bewährt. Die deklarative Systemverwaltung von Nix wurde zur Grundlage für immutable Infrastrukturen (siehe dazu den Bericht „Immutable Linux-Distros: Fedora Silverblue, OpenSUSE, Vanilla OS, Ubuntu Core Linux & Co.“). Diese Eigenschaft hat NixOS nebenbei auch zum Vorbild für andere Distributionen gemacht.

Zur Verwaltung von Softwarepakten macht sich NixOS die sogenannten Flakes zu Nutze mit dem Ziel, die Benutzerfreundlichkeit zu verbessern und die Reproduzierbarkeit von Software-Installationen zu optimieren. Flakes verwaltet Abhängigkeiten zwischen Nix-Ausdrücken, die die primären Protokolle zur Spezifikation von Paketen darstellen. Flakes implementiert diese Protokolle in einem konsistenten Schema mit einem gemeinsamen Satz von Richtlinien zur Verwaltung von Paketen.

Nix für deklarative Anwendungsorchestrierung

Mit seiner innovativen Herangehensweise kann sich der deklarative Paketmanager Nix – jenseits des reinen Systemmanagements – auch bei der Verwaltung einer Anwendungsbereitstellung in Kubernetes einbringen. Nix ermöglicht eine zuverlässige Paketierung von Anwendungen samt ihrer Abhängigkeiten. Dies vereinfacht die Erstellung von Docker-Containern für die Bereitstellung in einem Kubernetes-Cluster.

Mit Nix lassen sich konsistente und isolierte Entwicklungsumgebungen für Anwendungen einer Kubernetes-Bereitstellung auf eine reproduzierbare Art und Weise erstellen. Nix gewährleistet hierbei, dass die Entwicklungsumgebung der Produktionsumgebung entspricht.

Nix kann dann auch das laufende Management einer Bereitstellung übernehmen, einschließlich der Konfiguration von Kubernetes-Ressourcen wie Pods, Services und Ingress-Regeln. Nix „deklariert“ einfach die benötigten Kubernetes-Ressourcen in einer Nix-Konfigurationsdatei und fertig ist die Bereitstellung.

Die deklarative Herangehensweise erleichtert die Wartung und das Verständnis der Konfiguration. So kann man auch beispielsweise ConfigMaps und Secrets in Nix definieren, um sicherzustellen, dass die Konfiguration der Anwendung in verschiedenen Umgebungen konsistent bleibt.

Nix integriert sich vorzüglich in CI/CD-Pipelines und kann dadurch die Bereitstellung von Anwendungen in Kubernetes nicht zuletzt vorhersehbar automatisieren. Es reduziert die Komplexität beim Entwickeln und Orchestrieren von Anwendungen und Infrastrukturen in Kubernetes-Clustern, indem es eine konsistente Umgebung auf eine reproduzierbare Art und Weise bereitstellt.

NixOps

Die Bereitstellung und das Management von Cloud-Infrastrukturen im Nix-Ökosystem übernimmt ein Werkzeug namens NixOps, das eng mit Nix und NixOS integriert ist. NixOps kann die gesamte Infrastruktur, einschließlich Cloud-Server, -Konnektivität und anderer -Dienste, in Nix-Ausdrücken beschreiben und auf Cloud-Plattformen wie Amazon AWS, Google Cloud und anderen reproduzierbar bereitstellen.

Mit seiner effizienten Verwaltung der Konfigurationszustände von Cloud-Infrastrukturen ermöglicht NixOps eine atomare Evolution der betreffenden Softwarebereitstellung. Änderungen eines Cloud-Deployments werden entweder vollständig erfolgreich angewendet oder im Fehlerfall sauber rückgängig gemacht. Das erhöht nicht nur die Zuverlässigkeit von CloudOps, sondern minimiert nebenbei die Cloud-Kosten.

InvokeAI, eine Implementierung von Stable Diffusion, macht sich für die Verwaltung verzwickter KI-Abhängigkeiten den Nix-Stack zunutze.
InvokeAI, eine Implementierung von Stable Diffusion, macht sich für die Verwaltung verzwickter KI-Abhängigkeiten den Nix-Stack zunutze.
(Bild: Nixified.ai)

Das Projekt Nixified.ai nutzt den Nix-Stack für die Verpackung und Bereitstellung von KI-Software. Nix verwaltet die Abhängigkeiten und den Build-Prozess für jedes KI-Projekt im Repository, was eine hohe Reproduzierbarkeit und Isolation von anderen Systemkomponenten gewährleistet.

Mit InvokeAI bietet Nixified.ai eine Implementierung von Stable Diffusion, dem Open-Source Text-zu-Bild und Bild-zu-Bild Generator. Die Verwaltung verzwickter Abhängigkeiten, die den Prozess der Bildgenerierung unterstützen, verdankt das Projekt dem Nix-Ökosystem.

Der NixOS-Stack im Überblick.
Der NixOS-Stack im Überblick.
(Bild: Nixos.wiki)

Obwohl Nixified.ai eng mit dem Nix-Ökosystem verbunden ist, beschränkt es seine Nutzer/innen nicht notwendigerweise auf NixOS, die Linux-Distribution. Stattdessen ist die Lösung mit jeder Linux-Distribution und sogar mit Windows kompatibel, solange der Nix-Paketmanager installiert ist.

Schon wieder ein Problem mit Kubernetes? Macht doch nix!

„Was ist jetzt das Problem mit Kubernetes? In Kubernetes dreht sich alles um YAML. Es ist umständlich“ – argumentierte Vladimir Pouzanov in seiner Rede auf der NixCon2023 Anfang September – „Es ist redundant (...) es hat viele Vererbungsprobleme“. Die meisten Entwickler würden letztendlich „auf HELM standardisieren“.

Der Paketmanager Helm definiert und verwaltet Kubernetes-Ressourcen wie Pods, Services, Ingress-Regeln und dergleichen anderes als sogenannte „Charts“. Ein Helm-Chart ist eine Sammlung von vordefinierten, konfigurierbaren Kubernetes-Ressourcen – soweit so gut. Helm-Charts mögen ja hochgradig konfigurierbar sein, bieten jedoch keine Reproduzierbarkeit auf Systemebene. Nix kann im Gegensatz dazu über verschiedene Systeme hinweg Konsistenz und Reproduzierbarkeit schaffen.

Nix trumpft gegenüber Helm unter anderem auch in Bezug auf die Verwaltung von Abhängigkeiten. Helm stößt schnell auf seine Grenzen, sobald mehrere Charts ineinandergreifen. Nix bietet zudem eine granulare Kontrolle der Versionierung und einfache Rollbacks. Während auch Helm Rollback-Funktionen bereitstellt, ist der Ansatz von Nix in Bezug auf Systemzustände und die Versionskontrolle wesentlich ausgereifter und praxisnaher.

Mit Nix als einer Templating-Engine ließen sich viele der Herausforderungen von Kubernetes umgehen, insbesondere in Kombination mit anderen Tools wie dem nativen Konfigurationsmanager von Kubernetes, Kustomize. „Nehmen Sie Ihre Daten in welchem Format auch immer und ziehen Sie die durch Nix“, empfiehlt Vladimir Pouzanov. So ließen sich etwa Anweisungen in der Konfigurationssprache Jsonnet durch Nix ausführen.

NixOS ist auf eine hohe Systemstabilität ausgelegt und gewährleistet die konsequente Vermeidung von Abhängigkeitsproblemen und Paketkonflikten. Es hat jedoch eine steilere Lernkurve als Helm.

Eine Reihe von Nachahmern

Als die älteste deklarative Linux-Distribution hat NixOS im Laufe seines Bestehens zahlreiche Nachahmer inspiriert. Unter anderem das Guix System und Fedora Silverblue/Kinoite implementieren vergleichbare Ansätze, haben es jedoch mit der deklarativen Herangehensweise nicht ganz so weit getrieben wie NixOS.

Das Guix System entstand um den Paketmanager GNU Guix herum, der ähnlich wie Nix einen deklarativen und funktionalen Ansatz für das Paket- und Systemkonfigurationsmanagement anstrebt. Das Guix System ermöglicht es den Benutzern, die gesamte Systemkonfiguration deklarativ zu definieren, was sie reproduzierbar und wiederherstellungsfähig machen soll. Die Guix-Gemeinde ist jedoch wesentlich kleiner als das NixOS-Ökosystem. Letzteres bietet eine deutlich umfangreichere Sammlung von Softwarepaketen.

Während NixOS einen deklarativen und reproduzierbaren Ansatz für das Systemmanagement umsetzt, zielen Fedora Silverblue und Fedora Kinoite vorrangig auf ein immutables (unveränderliches) OS-Design ab, welches gegen Systemkorruption resistent sein will. „Immutable“ bedeutet in diesem Kontext, dass Änderungen am System in einer kontrollierten und vorhersagbaren Weise stattfinden mit dem Ziel, die Systemintegrität und -zuverlässigkeit zu maximieren.

Die beiden Varianten von Fedora verwenden eine Technologie namens OSTree, bei der das System basierend auf einem spezifischen versionierten Image semi-deklarativ zusammengestellt wird. Der Ansatz ist nicht derart vollständig deklarativ wie jener von NixOS oder Guix, hat jedoch ebenfalls zum Ziel, eine hohe Reproduzierbarkeit von Systemzuständen zu gewährleisten.

Fazit

Das Aufkommen unveränderlicher Linux-Distributionen reflektiert das wachsende Interesse an der Bereitstellung robuster und zuverlässiger Laufzeitumgebungen für moderne Anwendungsarchitekturen, Stichwort: Immutable Infrastructure.

NixOS mit seinem Paketmanager Nix hebt sich durch seine Fähigkeit hervor, komplexe Softwareumgebungen reproduzierbar bereitzustellen und deklarativ zu verwalten. Mit seiner wachsenden Gemeinde, der unermüdlich zielstrebigen Weiterentwicklung und der Unterstützung durch relevante Marktakteure bleibt NixOS ein faszinierendes Beispiel für ein Linux-Projekt, das seiner Zeit vorauseilt.

(ID:49836023)