Nix Flakes und die entsprechenden Funktionen in Guix
(coopi.neocities.org)- Nix Flakes bündeln Projektabhängigkeiten, Locking, Ausgabe-Schema und Entwicklungsumgebungen rund um
flake.nixundflake.lock, während Guix dieselbe Art von Funktionen durch die Kombination orthogonaler Werkzeuge wie Channels, Manifests,guix describe,guix shellundoperating-systembereitstellt - Flakes fixieren Abhängigkeiten über projektbezogene
inputsund ein automatisch erzeugtesflake.lock, während Guix mit benutzerbezogenemguix describe, einem im Projekt mit Commits festgehaltenenchannels.scmundguix time-machinereproduzierbare Umgebungen aufbaut - Reinheit wird bei Flakes durch restricted evaluation erzwungen, während sie in Guix durch die Struktur der Scheme-Module, explizite Eingaben und isolierte Build-Container von Grund auf erreicht wird
- Ausgabestruktur: Flakes bieten standardisierte Attrsets wie
packages,devShellsundnixosConfigurations, während Guix transparente Scheme-Records und Dateien wie<package>, Manifest,operating-systemund Service verwendet, die von den jeweiligen Befehlen direkt konsumiert werden - Auswahlkriterium: Wer einen einzelnen Einstiegspunkt und ein standardisiertes Schema bevorzugt, ist mit Flakes gut bedient; wer lieber kleine, unabhängige Werkzeuge kombiniert, fährt mit Guix besser
Zentrale Gegenüberstellung
- Es gibt keine einzelne Guix-Funktion, die einem Nix Flake entspricht; während Nix Flakes mehrere Probleme als ein großes Feature lösen, setzt Guix auf die Kombination kleinerer, orthogonaler Werkzeuge
- Guix hat den Nix-Daemon wiederverwendet und teilt sich die C++-Komponenten für Build-Isolation und Store-Management
- Guix implementiert den Großteil oberhalb des Nix-Daemons — etwa Sprache, Paketdefinitionen und Servicesystem — neu in Guile Scheme
- Guix und Nix teilen sich das Derivation-Format ATerm und die Abstammung des Daemons, aber die Struktur oberhalb des Daemons ist in Guix auf eigene Weise aufgebaut
- Guix verfügt über die Capabilities, die Flakes bieten, stellt sie aber in anderer Form bereit
Grundstruktur eines Nix Flake
- Ein Nix Flake ist ein Source Tree mit einer
flake.nix-Datei im Root und liegt meist als Git-Repository vor - Das Vorhandensein von
flake.nixmacht den Source Tree zu einem Flake; die Datei hat typischerweise eine Struktur mitdescription,inputsundoutputs descriptionist eine menschenlesbare Zeichenkette, die angibt, was der Flake bereitstelltinputsdeklarieren Abhängigkeiten wie andere Flakes, Git-Repos oder Tarballs; Nix lädt sie, evaluiert sie und übergibt sie dann an die Funktionoutputsoutputsist eine Funktion, die die aufgelösten Inputs und den speziellen Inputselfentgegennimmt und ein strukturiertes Attrset mit Paketen, Dev Shells, NixOS-Konfigurationen, Overlays usw. zurückgibt-
Beispielstruktur und Ausführungsziele
- Das Beispiel-
inputsmitnixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";bedeutet, dass der Branchnixos-unstableaus dem GitHub-RepositoryNixOS/nixpkgsgeholt wird - Der Beispiel-Flake verwendet
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ];undnixpkgs.lib.genAttrs, um Outputs für mehrere CPU-Architekturen zu erzeugen - Flakes verlangen die Ebene
packages.<system>; im Beispiel wird darunter dasdefault-Paket mitpkgs.buildGoModuledefiniert src = ./.;verwendet das gesamte Git-Repository als SourcedevShellsdefiniert die Entwicklungs-Shell, auf die sichnix developbezieht; im Beispiel werdenpkgs.mkShellundbuildInputs = with pkgs; [ go gopls gotools ];verwendet
- Das Beispiel-
-
flake.lockund reine Auswertung- Wenn ein Nix-Befehl für einen Flake ausgeführt wird, erzeugt Nix die JSON-Datei
flake.lock, die alle Inputs und transitiven Inputs auf exakte Revisionen festlegt flake.lockist eine Lock-Datei, die reproduzierbare Builds über Maschinen und Zeit hinweg ermöglicht- Flakes erzwingen pure evaluation:
$NIX_PATH,builtins.currentSystemund Umgebungsvariablen werden nicht implizit hereingegeben, alles muss explizit sein - Die von Flakes bereitgestellten Funktionen lassen sich zusammenfassen als Deklaration von Abhängigkeiten, Pinning von Abhängigkeiten, Erzwingung von Reinheit, Bereitstellung eines standardisierten Ausgabe-Schemas, reproduzierbares Teilen und Definition von Entwicklungsumgebungen
- Wenn ein Nix-Befehl für einen Flake ausgeführt wird, erzeugt Nix die JSON-Datei
Der entsprechende Ansatz von Guix
- Guix hatte bereits Lösungen für einen erheblichen Teil der Flakes-Funktionen, bevor Flakes am 1. November 2021 in Nix 2.4 eingeführt wurden
- Der Guix-Mechanismus für Channels wurde etwa 2018–2019 eingeführt
- Die Lösung von Guix ist orthogonal; statt eine einzelne monolithische Abstraktion zu übernehmen, können die jeweiligen Werkzeuge unabhängig voneinander verwendet werden
-
Channels und Deklaration von Abhängigkeiten
- In einem Flake werden Abhängigkeiten direkt in
flake.nixdeklariert; im Beispiel werdennixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";undhome-manager.url = "github:nix-community/home-manager";verwendet inputs.nixpkgs.follows = "nixpkgs";bei einem Flake-Input sorgt dafür, dass nicht das eigenenixpkgs-Input vonhome-managerverwendet wird, sondern dasnixpkgsdes aktuellen Flakes, und vermeidet so die Situation, dass zwei unterschiedlichenixpkgs-Kopien entstehen- Channels in Guix sind Git-Repositories, die Guile-Module enthalten; meist enthalten sie Paketdefinitionen, können aber auch Services, Systemkonfigurationen und beliebigen Scheme-Code umfassen
- Guix-Channels werden in
~/.config/guix/channels.scmdeklariert; diese Scheme-Datei gibt eine Liste von Channel-Records zurück guix pullholt und kompiliert alle Channels und macht die entsprechenden Module in allenguix-Kommandos verfügbar- Channels können mit der Datei
.guix-channelim Repository-Root Abhängigkeiten zu anderen Channels deklarieren - Channel-Abhängigkeiten in Guix sind den
inputseines Flakes grob ähnlich; beim Ausführen vonguix pullwerden auch transitive Channel-Abhängigkeiten mitgeholt
- In einem Flake werden Abhängigkeiten direkt in
-
Projektbezogene und benutzerbezogene Abhängigkeiten
- Flakes arbeiten projektbezogen, sodass jedes Repository seine eigene
flake.nixund eigene Inputs hat; Channels arbeiten systemweit oder pro Benutzer, sodasschannels.scmfür alleguix-Aufrufe gilt - Flakes unterstützen auf natürliche Weise, dass unterschiedliche Projekte unterschiedliche Abhängigkeitsmengen haben; in Guix verwendet man für denselben Effekt üblicherweise
guix time-machineoder separate Profile - Flakes verwenden eine URL-ähnliche Syntax wie
github:NixOS/nixpkgs,git+https://...; Channels verwenden einfache Git-URLs - Die Flake-Syntax ist für schnelle Referenzen ergonomischer, Channels sind einfacher und expliziter
- Flakes unterstützen mit
flake = false;auch Repositories ohneflake.nixals Non-Flake-Inputs - In Guix ist ein Channel ein Git-Repository mit Scheme-Dateien, daher ist kein besonderes Opt-in nötig; jedes Repository mit Guile-Modulen kann ein Channel sein
- Flakes arbeiten projektbezogen, sodass jedes Repository seine eigene
Pinning, Reproduzierbarkeit und Zeitreise
-
flake.lockflake.lockist ein JSON-Graph; alle Inputs werden auf genaue Commit-Hashes festgelegt, und Nix prüft dennarHash, also den Hash des vollständig geholten Source-Treesflake.lockwird ins Repository committed, sodass jeder, der es klont, dieselben Dependency-Versionen erhältoriginalinflake.lockist das angeforderte Ziel,lockeddas tatsächlich erhaltene Ziel- Das Two-Layer-System von
flake.lockermöglicht selektive Updates, bei denen zum Beispiel nur ein bestimmter Input mitnix flake lock --update-input nixpkgsaktualisiert wird und der Rest unverändert bleibt
-
guix describeundguix time-machine- Guix zeichnet beim Ausführen von
guix pulldie exakten Commits aller Channels auf, undguix describezeigt diese Informationen an - Die Ausgabe von
guix describeenthält Generationsnummer, Datum, Kennzeichnung des aktuellen Zustands, Channel-Namen, Repository-URL, Branch und Commit - Die aufgezeichneten Channel-Commits in Guix entsprechen einer Lock-Datei, liegen aber nicht als Datei im Projektverzeichnis vor, sondern als Guile-Profil in
~/.config/guix/current - Um reproduzierbare Umgebungen zu teilen, kann man in Guix
guix time-machineverwenden guix time-machine --commit=8a1ab328 -- shell -m manifest.scmfixiert zunächst Guix selbst auf eine bestimmte Revision und führt dannguix shellmit den Paketdefinitionen dieser Revision ausguix time-machinelädt und kompiliert bei Bedarf die betreffende Revision und erzeugt eine isolierte Umgebung, in der die Paketdefinitionen exakt dem Stand dieses Commits entsprechen- In Guix gibt es auch das Muster, ein
channels.scmmit festgelegten Commits ins Projekt-Repository einzuchecken guix time-machine -C channels.scm -- shell -m manifest.scmreproduziert die exakte Umgebung mithilfe des im Repository enthaltenenchannels.scm
- Guix zeichnet beim Ausführen von
-
Unterschiede zwischen beiden Ansätzen
flake.lockist projektbezogen und automatisch,guix describeist benutzerbezogen und automatisch- Ein
channels.scmmit festgelegten Commits bietet in Guix projektbezogenes Pinning, aber auf manuelle Weise - Guix arbeitet daran, die Ergonomie für projektbezogenes Pinning zu verbessern, aber der aktuelle Workflow erfordert ein expliziteres Setup
flake.lockist ein maschinenlesbarer JSON-Graph, das Guix-Gegenstück ist eine Scheme-Datei, die Channels mit Commit-Hashes auflistet- Beide Ansätze erreichen das Ziel des Dependency-Pinnings, aber der Flake-Lock ist durch den vollständigen Abhängigkeitsgraphen mit
original- undlocked-Einträgen für alle transitiven Inputs stärker strukturiert guix time-machineist eine Funktion ohne direktes Flake-Äquivalent; damit kann man nicht nur zu festgelegten Dependency-Versionen wechseln, sondern zum vollständig anderen historischen Zustand der Paketsammlung
Reinheitsmodell
- Flakes werden in einem eingeschränkten Evaluierungskontext ausgeführt; die Verwendung von
builtins.currentSystem,builtins.getEnvund$NIX_PATHist verboten oder wird ignoriert - In Flakes muss alles aus deklarierten Inputs stammen, sodass versehentliche Abhängigkeiten von implizitem Zustand schwer entstehen können
- Der Trade-off der reinen Evaluierung bei Flakes besteht darin, dass für die Systemerkennung an vielen Stellen explizite
system-Parameter nötig sind und Umgebungsvariablen nicht gelesen werden können - Wenn in Flakes ein unreinheitsbedingter Escape Hatch benötigt wird, muss explizit
--impureübergeben werden - Guix benötigt keinen separaten Modus für reine Evaluierung, da die Evaluierung konventionsgemäß bereits rein ist
- Guile-Module greifen nicht auf Umgebungsvariablen zu, sofern diese nicht explizit übergeben werden
- In Guix gibt es kein Gegenstück zu
$NIX_PATH; Pakete werden nicht über einen Suchpfad, sondern über das Modulsystem aufgelöst - In Guix gibt es kein Konzept, das
builtins.currentSystementspricht; Systeme werden explizit über Paketmetadaten und das Flag--systemangegeben - Auch die Builds in Guix sind rein; Builds laufen in isolierten Containern, in denen nur explizit deklarierte Inputs sichtbar sind
- In Guix-Builds gibt es keinen Zugriff auf
/usr/bin,/etcoder das Netzwerk; Ausnahmen für Netzwerkzugriff sind auf Fixed-Output-Derivations beschränkt - Das Build-Sandboxing von Nix und Guix folgt im Wesentlichen demselben Ansatz
- Guix erreicht Reinheit architektonisch durch die Struktur der Scheme-Module, während Flakes Reinheit erzwingen, indem sie einem ursprünglich unreineren System einen eingeschränkten Evaluierungsmodus aufsetzen
Ausgabe-Schema und Datenmodell
-
Flake-Ausgabe-Schema
- Flakes definieren ein Standardschema für Outputs;
packages.<system>.<name>wird vonnix buildverwendet,devShells.<system>.<name>vonnix developundapps.<system>.<name>vonnix run - Das Flake-Ausgabe-Schema umfasst außerdem
nixosConfigurations.<name>,overlays.<name>,nixosModules.<name>,formatter.<system>,templates.<name>undchecks.<system>.<name> - Die Standardisierung des Flake-Ausgabe-Schemas sorgt dafür, dass
nix build .,nix runundnix flake showauf konsistente Stellen verweisen, was die Auffindbarkeit erhöht - Ein Nachteil des Flake-Ausgabe-Schemas ist seine Starrheit; um beliebige Output-Typen hinzuzufügen, sind Änderungen an Nix selbst nötig, auch wenn es einen kleinen Erweiterungsmechanismus gibt
- Wegen des
<system>-Parameters muss Multi-Plattform-Support explizit behandelt werden; dafür werden Helper-Funktionen oder Bibliotheken wieforAllSystems,flake-utilsoderflake-partsverwendet
- Flakes definieren ein Standardschema für Outputs;
-
First-Class-Datentypen in Guix
- In Guix gibt es kein einzelnes Ausgabe-Schema wie bei Flakes, sondern First-Class-Datentypen, die von verschiedenen Befehlen genutzt werden können
- In Guix werden Pakete als
<package>-Records definiert und vonguix installsowieguix buildverwendet - In Guix werden Manifeste als Scheme-Dateien definiert und von
guix shell -msowieguix packageverwendet - In Guix werden Systemkonfigurationen als
operating-systemdefiniert und vonguix system reconfigureverwendet - In Guix werden Home-Konfigurationen als
home-environmentdefiniert und vonguix home reconfigureverwendet - In Guix werden Services als
<service>-Records definiert, die im Feldservicesvonoperating-systemverwendet werden - In Guix sind Channels Git-Repositories, die von
guix pullverwendet werden - In Guix sind Paketvarianten Scheme-Prozeduren; verwendet werden
--with-inputund--transform
-
Dateien und Paketdefinitionen
- Ein Guix-Projekt kann eine Kombination aus einem Channel mit Paketdefinitionen,
manifest.scmfür die Entwicklung,system.scmfür Deployment sowie Deklarationen wieoperating-systemoderhome-environmentbereitstellen - In Guix erfordern diese Dateien keine spezielle Entry-Point-Datei; es sind einfach Scheme-Dateien, die Scheme-Werte definieren
- In Guix verarbeitet der jeweilige Befehl die Datei, wenn man sie dem passenden
guix-Unterbefehl angibt; separate Zeremonie oder Schema-Validierung ist nicht nötig - Ein Beispiel für
manifest.scmdeklariert eine Entwicklungsumgebung, indem anspecifications->manifesteine Liste mit Paketnamen wie"guile","guile-git"und"guile-json"übergeben wird - Ein Beispiel für
mylib.scmdefiniert einen<package>-Record als Guix-Entsprechung zu einer Nix-Derivation; Paketfelder lassen sich programmatisch abfragen - Eine Beispiel-Paketdefinition enthält
(name "mylib"),(version "0.1.0"),(source (local-file ".")),(build-system gnu-build-system),(inputs (list guile guile-git)),(home-page "https://example.com")und(license gpl3+) local-filein Guix übernimmt Dateien aus dem aktuellen Verzeichnis zur Build-Zeit und ist ähnlich zusrc = ./.;in Nixgnu-build-systemin Guix folgt dem Muster./configure && make && make install; daneben gibt es weitere Build-Systeme wiecmake-build-systemundpython-build-system- Anders als in Nix, wo
stdenvimplizitgccundcoreutilsbereitstellt, hält Guix alle Abhängigkeiten explizit
- Ein Guix-Projekt kann eine Kombination aus einem Channel mit Paketdefinitionen,
Entwicklungsumgebungen
- Im Beispiel für
devShellsvon Flakes wirddevShells.x86_64-linux.default = pkgs.mkShell { buildInputs = with pkgs; [ go gopls gotools ]; shellHook = '' echo "Welcome to the devShell!" ''; };verwendet mkShellerzeugt eine Derivation, die beim Build eine Shell-Umgebung erstellt;buildInputswird in denPATHinnerhalb der Shell aufgenommen, undshellHookführt beim Betreten der Shell beliebigen Bash-Code aus- In eine Flake-Dev-Shell gelangt man mit
nix developoder für eine benannte Shell mitnix develop .#my-shell - Eine Guix-Entwicklungsumgebung kann in
manifest.scmdefiniert werden, indem anspecifications->manifesteine Liste von Package-Specification-Strings übergeben wird - Das beispielhafte Guix-Manifest deklariert
"go","gopls","go-tools" - Eine auf einem Guix-Manifest basierende Shell wird mit
guix shell -m manifest.scmgestartet - Für ad-hoc-Umgebungen kann Guix auch ohne Datei nur Package-Namen auf der Kommandozeile entgegennehmen, etwa
guix shell go gopls go-tools guix shellunterstützt--containerfür vollständige Isolation,--emulate-fhszum Ausführen von Programmen, die das Standard-Linux-Dateisystemlayout erwarten, und--nesting, um Guix innerhalb eines Guix-Containers auszuführen- Guix-Manifeste sind eigenständige Scheme-Dateien, die nicht in eine größere
flake.nix-Struktur eingebettet sind guix shellkann auch ohne Datei arbeiten, abernix developbenötigt ein Flake odershell.nixaus der Legacy-Schnittstelle- Flakes bieten benannte Dev-Shells wie
devShells.x86_64-linux.testunddevShells.x86_64-linux.default - Bei Guix-Manifests werden statt benannter Dev-Shells separate Dateien wie
manifest.scmundtest-manifest.scmnebeneinander verwendet - Sowohl Nix Flakes als auch Guix unterstützen containerisierte Entwicklung
Systemkonfiguration
-
NixOS und Flakes
- Im Beispiel für
nixosConfigurationsvon Flakes nimmtnixpkgs.lib.nixosSystemeine Liste von NixOS-Modulen entgegen und erzeugt eine vollständige System-Derivation einschließlich Kernel, Services, Konfigurationsdateien und mehr - Der Beispielbefehl für eine flakebasierte NixOS-Bereitstellung lautet
nixos-rebuild switch --flake .#myhost - Das beispielhafte
nixosConfigurations.myhostenthältsystem = "x86_64-linux";undmodules = [ ./configuration.nix home-manager.nixosModules.home-manager ]; - NixOS-Module verwenden ein Modulsystem mit prioritätsbasiertem Merging über
options,config,mkIf,mkDefaultundmkForce - Das NixOS-Modulsystem löst Prioritäten auf, selbst wenn mehrere Module dieselbe Option setzen, und erleichtert es so, Konflikte zu vermeiden, auch wenn Dutzende Module zur gleichen Konfiguration beitragen
- Im Beispiel für
-
Guix
operating-system- Guixs
operating-systemist keine Funktion, sondern ein Scheme-Record, dessen Felder benannte, typisierte Werte sind, die von Guix validiert werden - Der Beispielbefehl für eine Guix-Systembereitstellung lautet
guix system reconfigure config.scm - Das Beispiel für den
operating-system-Record enthält(host-name "myhost"),(timezone "Etc/UTC"), eine Bootloader-Konfiguration, Dateisysteme und Services - Das Beispiel für die Guix-Bootloader-Konfiguration verwendet
grub-efi-bootloadermit dem Ziel"/boot/efi"; Guix unterstützt unter anderem GRUB und U-Boot - Guix-Dateisysteme werden als Liste deklariert, und
%base-file-systemsliefert Standardwerte für/dev,/proc,/sysund weitere - Guix-Services bilden einen gerichteten azyklischen Graphen (DAG), und jeder Service kann andere Services erweitern
%base-servicesstellt essenzielle Services wie das Init-System Shepherd, Syslog und Netzwerkdienste bereit- Für die Guix-Systemkonfiguration ist kein spezieller Output-Typ erforderlich; es genügt,
guix systemeine Datei zu übergeben, die einenoperating-system-Record zurückgibt - Die Service-Kombination in Guix macht es leicht, neue Services zu schreiben, die sich auf beliebige Weise an ein bestehendes System andocken
- Guixs
Auffindbarkeit und Registry
- Flakes haben mit
flake.nixeinen standardisierten Einstiegspunkt, der Projektabhängigkeiten, Outputs und ein auffindbares Schema in einer Datei deklariert - Guix-Projekte können konventionsbasierte Dateien wie
manifest.scm,channels.scm,guix.scmundpackage.scmverwenden - Es gibt Bestrebungen,
guix.scmals Projektdatei zu standardisieren, die vonguix shellautomatisch erkannt wird, aber das ist noch nicht so etabliert wieflake.nix - Flakes haben mit flake-registry eine globale Registry, die Kurznamen auf URLs abbildet; Beispiele sind
nix run nixpkgs#helloundnix build github:NixOS/nixpkgs#firefox - Guix nutzt für ähnliche Bequemlichkeit Paketangaben, etwa
guix shell helloundguix install firefox - Guix hat kein Pendant zu einer Registry, die beliebige Git-Repositories über Kurznamen referenziert, sondern verwendet URLs direkt
- Die Nix-Registry war immer wieder eine Quelle von Verwirrung, weil nicht stets klar ist, ob
nixpkgsein Registry-Eintrag, ein lokaler Pfad oder ein anderes Ziel ist nix flake showist ein Befehl, der alles, was ein Flake anbietet, in einer Baumansicht anzeigt- Guix bietet
guix searchfür Pakete undguix system searchfür Services, aber keinen entsprechenden Befehl, der alles zeigt, was ein bestimmtes Projekt oder Repository bereitstellt; dafür muss man die Scheme-Dateien direkt prüfen - Flakes sind bei der Auffindbarkeit stark, weil
nix flake showeine konsistente Sicht auf das bietet, was ein Projekt bereitstellt - Guix-Projekte sind eher ad hoc; man muss wissen, welche Dateien man ansehen muss, und es gibt keine standardisierte Datei mit einem einzigen Einstiegspunkt
- Guix ist stark in der Flexibilität, weil alles Scheme ist und sich Dinge ohne Schema beliebig definieren und kombinieren lassen
Paketmodell und Umschreiben von Graphen
- In Nix sind Pakete Funktionen, die über einen Aufruf von
stdenv.mkDerivation { ... }eine Derivation zurückgeben; das Ergebnis ist ein undurchsichtiges Attributset. - In Guix sind Pakete
<package>-Records, also transparente Datenstrukturen mit benannten Feldern, die sich mit Standard-Scheme-Prozeduren untersuchen, transformieren und kombinieren lassen. - Da Guix-Paketdefinitionen keine opaque functions, sondern transparente Records sind, können
inspectundtransformohne spezielles Tooling programmatisch durchgeführt werden. - In Guix sind Pakete Daten, daher lassen sich graph rewrites leicht durchführen.
- In Guix kann man mit
package-input-rewritingausdrücken, dass der gesamte Abhängigkeitsgraph durchlaufen undperldurchperl-minimalersetzt wird. - Das Schlüsselwort
inheritin Guix definiert ein Paket neu, indem es alle Felder voncoreutilsübernimmt und nur die angegebenen Felder überschreibt. - In Nix gibt es mit ähnlicher Zielsetzung Overlays, doch wegen der undurchsichtigen Funktionsschnittstelle sind Untersuchung und Transformation schwieriger und weniger benutzerfreundlich.
Sicherheitsupdates, Bootstrapping, Authentifizierung
- Grafting in Guix ermöglicht es, Sicherheitsupdates in einem Abhängigkeitsbaum anzuwenden, ohne alle abhängigen Pakete neu zu bauen.
- Wenn eine Low-Level-Bibliothek wie glibc eine Schwachstelle hat, kann Guix Store-Pfade umschreiben und sie durch eine gepatchte Version ersetzen.
- Nix baut bei Sicherheitsupdates alles neu; bei großen Abhängigkeitsbäumen kann das mehrere Stunden Unterschied bei der Build-Zeit ausmachen.
- Guix legt starken Fokus auf quellbasiertes Bootstrapping, sodass sich das gesamte System aus einer kleinen Vertrauensbasis heraus bauen lässt.
- Die Bootstrapping-Kette von Guix beginnt bei einem etwa 500 Byte großen hex assembler und führt über den in Scheme geschriebenen
mes-C-Compiler undtccbis zur vollständigen GNU-Toolchain. - Das Projekt bootstrappable builds behandelt die Details des vollständigen Source-Bootstrappings.
- Nix ist stärker als Guix auf binäre Seeds angewiesen.
- Wenn sich die Bootstrapping-Kette nicht auditieren lässt, kann nicht vollständig verifiziert werden, ob das System tatsächlich aus dem vorgesehenen Quellcode gebaut wurde; vollständiges Source-Bootstrapping ist daher wichtig für Vertrauen und Verifizierbarkeit.
- Guix-Channels unterstützen standardmäßig kryptografische Authentifizierung.
- Ein Guix-Channel gibt eine „introduction“ an, die aus einem bestimmten Commit und dessen Ed25519-Signatur besteht; Guix verifiziert die gesamte Signaturkette von dieser Introduction bis zum aktuellen Commit.
- Flakes verwenden HTTPS und die GitHub-Infrastruktur als Vertrauensmodell; das ist ein anderes Sicherheitsmodell als die Ed25519-Channel-Authentifizierung von Guix.
Zentrale Entsprechungen in der Übersichtstabelle
- Bei der Deklaration von Abhängigkeiten verwenden Flakes
inputsinflake.nix, Guix verwendetchannels.scmund.guix-channel. - Für das Fixieren von Abhängigkeiten nutzen Flakes automatisch und projektspezifisch
flake.lock, während Guix benutzerspezifisch automatischguix describeund projektspezifisch manuell commit-fixiertechannels.scmverwendet. - Reine Auswertung wird im Flake-Modus erzwungen und ist in Guix von Haus aus Teil des Designs.
- Beim Ausgabeschema verwenden Flakes ein strukturiertes Attrset in
outputs, Guix dagegen ad-hoc Scheme-Records. - Für Entwicklungsumgebungen verwenden Flakes
devShellsundnix develop, Guixmanifest.scmundguix shell. - Für die Systemkonfiguration verwenden Flakes
nixosConfigurationsund das Modulsystem, Guixoperating-systemund einen Service-DAG. - Reproduzierbarkeit per Ein-Kommando-Aufruf hat bei Flakes die Form
nix build github:foo/bar, bei Guix die Formguix time-machine -C channels.scm -- build. - Projektspezifisches Fixieren wird bei Flakes automatisch über
flake.lockerledigt, bei Guix manuell überchannels.scmmit Commit-Angabe. - Für Auffindbarkeit bieten Flakes
nix flake show, während Guix auf die Untersuchung von Scheme-Modulen setzt. - Beim Paketmodell sind Flakes/Nix undurchsichtige Funktionen, Guix verwendet transparente Records.
- Als init system verwendet Nix systemd, Guix GNU Shepherd.
- Bei Sicherheitsupdates setzt Nix auf kompletten Rebuild, Guix auf schnelles Grafting.
- Beim Bootstrap-Vertrauen basiert Nix auf binären Seeds, Guix auf vollständigem Source-Bootstrapping.
- Für authentifizierte Updates setzt Flakes auf Vertrauen in HTTPS/GitHub, Guix auf Ed25519-Channel-Authentifizierung.
- FHS-Unterstützung bietet Nix mit
buildFHSUserEnv, Guix mit--emulate-fhs. - Jenseits von Linux unterstützt Nix macOS über nix-darwin, Guix ist auf GNU Hurd ausgerichtet.
- Hinsichtlich ausschließlicher Freie-Software-Ausrichtung ist Nix nicht ausschließlich darauf beschränkt und konfigurierbar, während Guix den FSDG entspricht.
Fazit
- Flakes und Guix lösen dieselben Problemklassen rund um Reproduzierbarkeit, Abhängigkeitsmanagement und Systemdeklaration, aber mit unterschiedlichen Architekturphilosophien.
- Flakes kommen einer einzelnen Funktion nahe: eine Datei, ein Schema, eine Lock-Datei, ein Satz von Konventionen.
- Guix ist eine Kombination orthogonaler Werkzeuge wie Channels für Distribution, Manifeste für Umgebungen,
operating-systemfür Konfiguration,guix time-machinefür Reproduzierbarkeit und Scheme-Records für andere Strukturen. - Wenn man eine standardisierte Vorgehensweise, eine einzige Einstiegspunkt-Datei, ein einziges Ausgabeschema und ein einziges Lock-Format bevorzugt, passen Flakes ganz natürlich.
- Wenn man bevorzugt, kleine unabhängige Werkzeuge zu kombinieren, sodass jedes Werkzeug im Sinne der Unix-Philosophie eine Sache gut macht, passt Guix gut.
- Beide Ökosysteme haben sich rund um die Idee entwickelt, dass Paketverwaltung funktional, deklarativ und reproduzierbar sein sollte, und treiben dieselbe Idee mit unterschiedlichen Implementierungen voran.
1 Kommentare
Lobste.rs-Meinungen
Diese Seite ist auf Mobilgeräten viel zu frustrierend zu lesen: Die Schrift ist etwas zu klein, und beim Scrollen stört sie ständig
Nach dem ersten Vergleich konnte ich nicht mehr weiterlesen, weil ich ständig zum Inhaltsverzeichnis zurückgesprungen bin
Auch nach dem Lesen des Artikels ist mir noch nicht klar, wie man die Abhängigkeiten eines Projekts angeben und pinnen soll. Es sieht so aus, als müsste man zum Veröffentlichen und Teilen die Commit-Hashes jeder transitiven Abhängigkeit manuell in
channels.scmeintragentime-machinescheint nur auf die Guix-Paketmenge zu wirken, nicht auf Abhängigkeiten außerhalb des BaumsWie bei
nix run github:nixos/nixpkgs/<commit hash>#<package>kann man auch Code aus einem früheren Stand von nixpkgs ziemlich einfach ausführenEin ungewöhnlicher Punkt bei Guix ist, dass die Version der Paketsammlung und die Version des Paketmanagers nicht getrennt werden. Um alte Pakete auszuführen, startet man damit auch eine alte Guix-Release mit, und ich verstehe nicht recht, warum man das wollen sollte
Im Artikel wird gesagt, dass man bei Flakes Commits manuell suchen und angeben müsse, und direkt danach wird als Beispiel ein Guix-Befehl gezeigt, bei dem ebenfalls Commits angegeben werden müssen. In Nix Flakes kann man die nixpkgs-Version auch mit
--override-inputüberschreiben, aber das ist unsauber, und genau das ist einer der Punkte, die unflake verbessern willNormalerweise entwickelt man in einer dedizierten
guix shell-Umgebung und wenn es ans Teilen geht, schreibt man mitguix describe -f channels > channels.scmalle Commit-Hashes inchannels.scmWenn man die Doku zu declaring channel dependencies liest, kann man Commit-Hashes für Abhängigkeiten angeben, aber es scheint keine Option zu geben, zu prüfen, ob auch die Abhängigkeiten dieser Abhängigkeiten auf bestimmte Commits festgelegt sind
Die
--commit=-Schreibweise vontime-machinebezieht sich auf den Guix-Channel, aber mit-Ckann man zusätzlich Channels aus einer Datei ladenDas hat den Vorteil, dass man trotz inkompatibler Änderungen am Paketmanager und an den Paketdefinitionen Historie und Reproduzierbarkeit behält
Allerdings müsste man dafür für jeden Commit einen nixpkgs-Checkout machen, wodurch die anfänglichen Erstellungskosten sehr hoch wären. Wenn der Index einmal existiert, dürften die Pflegekosten gering sein
Ich habe coopi auf die Probleme der Seite und auf diesen Thread hingewiesen, hoffentlich wird es bald behoben
Als jemand, der inzwischen stark zu Guix tendiert, würde ich mir wie von coopi gesagt auch für Guix eine standardisierte Datei bzw. ein standardisiertes Verzeichnis wünschen, die alles enthalten, also so etwas wie eine einzelne
flake.nixoder einnix-Verzeichnis. Allerdings könnte das unmöglich sein, weil man zum Importieren von Scheme-Modulen die richtigen Pfade angeben mussIn diesem Lobsters-Post steht, worüber der Autor spricht, daher scheinen die Tags
nixundlispauszureichenlinuxwegzulassen, nicht überzeugend. Das ist schließlich der einzige Kernel, den beide gemeinsam haben :P Allerdings passtunix, wie gesagt, wahrscheinlich wirklich nicht gutZum Beispiel so: Und ein Befehl
guix channel, der beim Erstellen und Verwalten neuer Channels hilft, wäre ebenfalls nützlichIch frage mich, ob es in Guix auch eine Funktion gibt, mit der man wie bei
.inputs.nixpkgs.followsin Nix Flakes Pins transitiver Abhängigkeiten überschreiben kannAußerdem erinnert mich ein großer Teil der Guix-Beschreibung des Autors an Nix vor Flakes: keine standardisierten Einstiegspunkte, eine Struktur mit Channels usw. Allerdings wirkt es so, als seien dieselben Muster in Guix weniger schmerzhaft, weil es dort ein Typsystem und eine echte Sprache gibt. Es fühlt sich wie eine Alternativgeschichte dazu an, wie Nix hätte aussehen können, wenn es besser oder in einer anderen Sprache gewesen wäre
Wegen der in anderen Kommentaren angesprochenen Usability-Probleme zögere ich, den Artikel zu empfehlen. Ich habe es nicht bemerkt, weil ich NoScript benutze und JavaScript standardmäßig deaktiviert habe
Trotzdem kam dieser Artikel genau zum richtigen Zeitpunkt. Bei uns in der Firma geht es stark in Richtung Nix, und wir schlagen uns ein wenig mit Flakes herum, aber die Erklärung in diesem Artikel war viel klarer als in früheren Texten, die ich gelesen habe
Antwort von Coopi: Er habe heute Morgen Änderungen vorgenommen, sie wegen der Arbeit aber nicht testen können, und dabei sei ihm aufgefallen, dass es ein Problem mit JavaScript gab
Diese Seite ist auf iOS-Mobilgeräten nicht benutzbar. Es sieht so aus, als würde die Seite unten laden und dann sofort nach oben scrollen, und sobald ich mehr als eine Bildschirmhöhe nach unten scrolle, wird irgendetwas ausgelöst, das mich wieder nach oben wirft
Der Lesemodus funktioniert, aber dabei gehen die Hervorhebungen und das eigentlich ziemlich gute Detail-Styling verloren
Es ist zwar richtig zu sagen, dass man das, was Flakes leisten, in Guix auch mit mehreren Werkzeugen erreichen kann, aber man sollte erwähnen, dass Nix schon früher und auch heute noch kleine, orthogonale Werkzeuge hatte, mit denen sich dieselben Probleme lösen lassen
Was Flakes bieten, ist ein standardisierter Projekteinstiegspunkt und das Ökosystem, das dadurch möglich wird, etwa eine Registry. Im Artikel wird auch gesagt, dass Guix diesen Teil nicht hat
Guix-Nutzer können zu dem Schluss kommen, dass ein standardisierter Einstiegspunkt nicht nötig ist, und viele Nix-Nutzer sind historisch ebenfalls zu diesem Schluss gekommen
Aber zu sagen, man könne Flakes mit einer Sammlung orthogonaler Werkzeuge nachbilden, klingt ein bisschen so, als würde man behaupten, FreeBSD brauche keine OCI-Unterstützung, weil man mit Jails alles Nötige machen könne. Das verpasst den Punkt, dass Standardisierung ein Ökosystem ermöglicht
Ich interessiere mich sehr für Guix und habe auch ein wenig dazu beigetragen, aber ich würde gern vergleichen, warum das Bauen mit
guix time-machinezusammen mitchannels.scmso viel länger dauert als das Ändern von Flake-Pins und die Nix-Auswertung. Wenn es etwa dreimal so langsam wäre, also zum Beispiel 5–10 Sekunden statt 15–30 Sekunden, könnte ich damit leben, aber bei meinen Versuchen lag es weit darüber