1 points par GN⁺ 5 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Les Nix Flakes regroupent les dépendances d’un projet, leur verrouillage, le schéma de sortie et l’environnement de développement autour de flake.nix et flake.lock, tandis que Guix fournit le même type de fonctionnalités via une combinaison d’outils orthogonaux comme les channels, les manifests, guix describe, guix shell et operating-system
  • Les Flakes figent les dépendances via des inputs par projet et un flake.lock généré automatiquement, tandis que Guix construit des environnements reproductibles avec guix describe côté utilisateur, un channels.scm consignant les commits du projet, et guix time-machine
  • La pureté est imposée dans les Flakes par une évaluation restreinte, alors que dans Guix elle est obtenue par conception grâce à la structure des modules Scheme, à des entrées explicites et à des conteneurs de build isolés
  • Pour la structure des sorties, les Flakes fournissent un attrset standard comme packages, devShells ou nixosConfigurations, tandis que Guix utilise des enregistrements et fichiers Scheme transparents comme <package>, manifest, operating-system et service, consommés directement par chaque commande
  • Le critère de choix est simple : si vous préférez un point d’entrée unique et un schéma standard, les Flakes conviennent mieux ; si vous préférez combiner de petits outils indépendants, Guix est plus adapté

Comparaison essentielle

  • Il n’existe pas de fonctionnalité Guix unique correspondant à un flake Nix ; là où Nix Flakes résout plusieurs problèmes avec une seule grande fonctionnalité, Guix y répond par une combinaison d’outils plus petits et orthogonaux
  • Guix a réutilisé le daemon de Nix et partage ses composants C++ chargés de l’isolation des builds et de la gestion du store
  • Guix a réimplémenté en grande partie en Guile Scheme tout ce qui se trouve au-dessus du daemon de Nix, notamment le langage, les définitions de paquets et le système de services
  • Guix et Nix partagent le format de dérivation ATerm et la lignée du daemon, mais la structure au-dessus du daemon est organisée selon la propre approche de Guix
  • Guix possède les capacités offertes par Flakes, mais les présente sous une autre forme

Structure de base d’un Nix Flake

  • Un Nix flake est un arbre de sources contenant un fichier flake.nix à sa racine, généralement sous la forme d’un dépôt Git
  • La présence de flake.nix fait de l’arbre de sources un flake, et le fichier suit une structure avec des éléments comme description, inputs et outputs
  • description est une chaîne lisible par un humain indiquant ce que le flake fournit
  • inputs déclare les dépendances, comme d’autres flakes, des dépôts Git ou des tarballs ; Nix les récupère, les évalue, puis les transmet à la fonction outputs
  • outputs est une fonction qui reçoit les entrées résolues et une entrée spéciale self, puis renvoie un attrset structuré contenant des paquets, des shells de développement, des configurations NixOS, des overlays, etc.
  • Structure d’exemple et cibles d’exécution

    • Dans l’exemple, nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; dans inputs signifie qu’on récupère la branche nixos-unstable du dépôt NixOS/nixpkgs sur GitHub
    • Le flake d’exemple utilise supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ]; et nixpkgs.lib.genAttrs pour générer des sorties pour plusieurs architectures CPU
    • Les Flakes exigent un niveau packages.<system> et, dans l’exemple, le paquet default sous packages est défini avec pkgs.buildGoModule
    • src = ./.; signifie que l’ensemble du dépôt Git est utilisé comme source
    • devShells définit les shells de développement référencés par nix develop ; dans l’exemple, on utilise pkgs.mkShell avec buildInputs = with pkgs; [ go gopls gotools ];
  • flake.lock et évaluation pure

    • Lorsqu’une commande Nix est exécutée sur un flake, Nix génère le fichier JSON flake.lock, qui fige chaque entrée et chaque dépendance transitive sur une révision précise
    • flake.lock est un fichier de verrouillage qui permet la reproductibilité des builds d’une machine à l’autre et dans le temps
    • Les Flakes imposent une évaluation pure : $NIX_PATH, builtins.currentSystem et les variables d’environnement ne peuvent pas être injectés implicitement, tout doit être explicite
    • Les fonctions assurées par les Flakes se résument ainsi : déclaration des dépendances, verrouillage des dépendances, application de la pureté, fourniture d’un schéma de sortie standard, partage reproductible et définition d’environnements de développement

L’approche équivalente de Guix

  • Guix disposait déjà de solutions pour une grande partie des fonctionnalités de Flakes avant l’introduction de Flakes dans Nix 2.4 le 1er novembre 2021
  • Le mécanisme de channels de Guix a été introduit vers 2018-2019
  • La solution de Guix est orthogonale : elle n’adopte pas une abstraction monolithique unique et permet d’utiliser chaque outil indépendamment
  • Channels et déclaration des dépendances

    • Dans un flake, les dépendances sont déclarées directement dans flake.nix, et l’exemple utilise nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; ainsi que home-manager.url = "github:nix-community/home-manager";
    • Dans les inputs d’un flake, inputs.nixpkgs.follows = "nixpkgs"; permet à home-manager de ne pas reprendre son propre input nixpkgs, mais d’utiliser celui du flake courant, ce qui évite de se retrouver avec deux copies différentes de nixpkgs
    • Les channels de Guix sont des dépôts Git contenant des modules Guile ; ils contiennent en général des définitions de paquets, mais peuvent aussi inclure des services, des configurations système et du code Scheme arbitraire
    • Les channels de Guix sont déclarés dans ~/.config/guix/channels.scm, et ce fichier Scheme renvoie une liste d’enregistrements de channel
    • guix pull récupère et compile tous les channels, puis rend ces modules utilisables par toutes les commandes guix
    • Les channels peuvent déclarer des dépendances envers d’autres channels via le fichier .guix-channel à la racine du dépôt
    • Les dépendances entre channels dans Guix sont globalement similaires aux inputs d’un flake, et les dépendances transitives des channels sont également récupérées lors de l’exécution de guix pull
  • Dépendances par projet et dépendances par utilisateur

    • Les Flakes fonctionnent par projet : chaque dépôt possède son propre flake.nix et ses propres inputs, tandis que les channels fonctionnent au niveau système ou utilisateur, et le channels.scm s’applique à toutes les invocations de guix
    • Les Flakes permettent naturellement à différents projets d’avoir des ensembles de dépendances différents ; dans Guix, on utilise généralement guix time-machine ou des profils séparés pour obtenir le même effet
    • Les Flakes utilisent une syntaxe de type URL comme github:NixOS/nixpkgs, git+https://..., tandis que les channels utilisent des URL Git classiques
    • La syntaxe des Flakes est plus ergonomique pour les références rapides, tandis que les channels sont plus simples et plus explicites
    • Les Flakes prennent en charge des entrées non-flake pour des dépôts sans flake.nix via flake = false;
    • Dans Guix, un channel est un dépôt Git contenant des fichiers Scheme ; aucun opt-in particulier n’est donc nécessaire, et tout dépôt contenant des modules Guile peut devenir un channel

Verrouillage, reproductibilité et voyage dans le temps

  • flake.lock

    • flake.lock est un graphe JSON dans lequel chaque input est épinglé à un hash de commit précis, et Nix vérifie le narHash, c’est-à-dire le hash de l’arbre source complet récupéré
    • flake.lock est commité dans le dépôt, de sorte que toute personne qui clone le projet obtient les mêmes versions de dépendances
    • Dans flake.lock, original désigne la cible demandée et locked la cible effectivement obtenue
    • Le système à deux niveaux de flake.lock permet des mises à jour sélectives, comme avec nix flake lock --update-input nixpkgs, en ne mettant à jour qu’un input précis tout en conservant les autres
  • guix describe et guix time-machine

    • Guix enregistre les commits exacts de tous les channels lors de l’exécution de guix pull, et guix describe affiche ces informations
    • La sortie de guix describe inclut le numéro de génération, la date, l’indication du statut courant, le nom du channel, l’URL du dépôt, la branche et le commit
    • Les commits de channels enregistrés par Guix correspondent à un lock file, mais ils se trouvent sous la forme d’un profil Guile dans ~/.config/guix/current plutôt que dans un fichier du répertoire du projet
    • Pour partager un environnement reproductible, on peut utiliser guix time-machine dans Guix
    • guix time-machine --commit=8a1ab328 -- shell -m manifest.scm épingle d’abord Guix à une révision donnée, puis exécute guix shell avec les définitions de paquets de cette révision
    • guix time-machine télécharge et compile cette révision si nécessaire, puis crée un environnement isolé où les définitions de paquets correspondent exactement à l’état de ce commit
    • Il existe aussi dans Guix un modèle consistant à versionner dans le dépôt du projet un channels.scm contenant des commits épinglés
    • guix time-machine -C channels.scm -- shell -m manifest.scm reproduit exactement l’environnement en utilisant le channels.scm inclus dans le dépôt
  • Différences entre les deux approches

    • flake.lock est automatique et par projet, tandis que guix describe est automatique et par utilisateur
    • Un channels.scm contenant des commits épinglés fournit un verrouillage par projet dans Guix, mais de manière manuelle
    • Guix travaille à améliorer l’ergonomie du verrouillage par projet, mais le workflow actuel demande encore une configuration plus explicite
    • flake.lock est un graphe JSON lisible par machine, tandis que son équivalent côté Guix est un fichier Scheme listant des channels avec leurs hashes de commit
    • Les deux approches atteignent l’objectif d’épinglage des dépendances, mais le verrouillage des flakes est plus structuré, car il fournit un graphe complet de dépendances avec des entrées original et locked pour tous les inputs transitifs
    • guix time-machine est une fonctionnalité sans équivalent direct dans les flakes : elle permet de remonter non seulement à des versions de dépendances épinglées, mais aussi à un état historique complètement différent de la collection de paquets

Modèle de pureté

  • Les Flakes s’exécutent dans un contexte d’évaluation restreint, où l’usage de builtins.currentSystem, builtins.getEnv et de $NIX_PATH est interdit ou ignoré
  • Dans les Flakes, tout doit provenir des entrées déclarées, ce qui rend plus difficile la création de dépendances accidentelles à un état implicite
  • Le compromis de l’évaluation pure des Flakes est qu’elle exige des paramètres system explicites à de nombreux endroits pour la détection du système, et qu’elle ne permet pas de lire les variables d’environnement
  • Lorsqu’une échappatoire impure est nécessaire dans les Flakes, il faut passer explicitement --impure
  • Guix n’a pas besoin d’un mode d’évaluation pure distinct, car l’évaluation y est déjà pure par convention
  • Les modules Guile n’accèdent pas aux variables d’environnement sauf si elles leur sont explicitement transmises
  • Guix n’a pas d’équivalent à $NIX_PATH, et résout les packages via le système de modules plutôt que par un chemin de recherche
  • Guix n’a pas de concept équivalent à builtins.currentSystem, et les systèmes sont spécifiés explicitement via les métadonnées des packages et l’option --system
  • Les builds de Guix sont également purs, et s’exécutent dans des conteneurs isolés qui ne voient que les entrées explicitement déclarées
  • Dans les builds Guix, il n’y a ni /usr/bin, ni /etc, ni accès réseau ; les exceptions d’accès réseau sont limitées aux dérivations à sortie fixe
  • En matière de sandboxing de build, Nix et Guix partagent fondamentalement la même approche
  • Guix atteint la pureté au niveau de l’architecture grâce à la structure des modules Scheme, tandis que Flakes impose la pureté en superposant un mode d’évaluation restreint à un système initialement impur

Schéma de sortie et modèle de données

  • Schéma de sortie des Flakes

    • Les Flakes définissent un schéma standard pour les outputs ; packages.<system>.<name> est utilisé par nix build, devShells.<system>.<name> par nix develop, et apps.<system>.<name> par nix run
    • Le schéma de sortie des Flakes inclut aussi nixosConfigurations.<name>, overlays.<name>, nixosModules.<name>, formatter.<system>, templates.<name> et checks.<system>.<name>
    • La standardisation du schéma de sortie des Flakes permet à nix build ., nix run et nix flake show de pointer vers des emplacements cohérents, ce qui améliore la découvrabilité
    • L’inconvénient du schéma de sortie des Flakes est sa rigidité ; ajouter des types de sortie arbitraires exige de modifier Nix lui-même, même s’il existe un petit mécanisme d’extension
    • À cause du paramètre <system> des Flakes, la prise en charge multiplateforme doit être gérée explicitement, et des fonctions utilitaires ou bibliothèques comme forAllSystems, flake-utils ou flake-parts sont utilisées
  • Types de données de première classe dans Guix

    • Guix n’a pas de schéma de sortie unique comme Flakes, mais des types de données de première classe que différentes commandes peuvent consommer
    • Dans Guix, les packages sont définis comme des enregistrements <package> et utilisés par guix install et guix build
    • Dans Guix, les manifests sont définis comme des fichiers Scheme et utilisés par guix shell -m et guix package
    • Dans Guix, les configurations système sont définies avec operating-system et utilisées par guix system reconfigure
    • Dans Guix, les configurations home sont définies avec home-environment et utilisées par guix home reconfigure
    • Dans Guix, les services sont définis comme des enregistrements <service> et utilisés dans le champ services de operating-system
    • Dans Guix, les channels sont des dépôts Git et guix pull les utilise
    • Dans Guix, les variantes de packages sont des procédures Scheme et --with-input ainsi que --transform sont utilisés
  • Fichiers et définitions de packages

    • Un projet Guix peut combiner et fournir un channel contenant des définitions de packages, un manifest.scm pour le développement, un system.scm pour le déploiement, ainsi que des déclarations operating-system ou home-environment
    • Dans Guix, ces fichiers n’exigent pas de fichier spécial de point d’entrée ; ce sont simplement des fichiers Scheme qui définissent des valeurs Scheme
    • Dans Guix, il suffit d’indiquer le fichier à la sous-commande guix concernée pour que la commande le traite, sans cérémonie supplémentaire ni validation de schéma
    • Un exemple de manifest.scm déclare un environnement de développement en passant à specifications->manifest une liste de noms de packages "guile", "guile-git", "guile-json"
    • Un exemple de mylib.scm définit un enregistrement <package>, l’équivalent dans Guix d’une dérivation Nix, dont les champs de package peuvent être interrogés de manière programmatique
    • Un exemple de définition de package comprend (name "mylib"), (version "0.1.0"), (source (local-file ".")), (build-system gnu-build-system), (inputs (list guile guile-git)), (home-page "https://example.com";), (license gpl3+)
    • Dans Guix, local-file récupère au moment du build les fichiers du répertoire courant, de façon similaire à src = ./.; dans Nix
    • Dans Guix, gnu-build-system correspond à l’approche ./configure && make && make install, et Guix propose aussi d’autres systèmes de build comme cmake-build-system ou python-build-system
    • Contrairement à Nix, où stdenv fournit implicitement gcc et coreutils, Guix rend toutes les dépendances explicites

Environnements de développement

  • L’exemple de devShells dans Flakes utilise devShells.x86_64-linux.default = pkgs.mkShell { buildInputs = with pkgs; [ go gopls gotools ]; shellHook = '' echo "Welcome to the devShell!" ''; };
  • mkShell crée une dérivation qui produit un environnement shell au moment du build ; buildInputs est ajouté au PATH du shell et shellHook exécute du bash arbitraire à l’entrée dans le shell
  • On entre dans un dev shell Flake avec nix develop ou, pour un shell nommé, nix develop .#my-shell
  • Un environnement de développement Guix peut être défini dans manifest.scm en passant une liste de chaînes de spécification de paquets à specifications->manifest
  • Le manifest Guix d’exemple déclare "go", "gopls", "go-tools"
  • On entre dans un shell basé sur un manifest Guix avec guix shell -m manifest.scm
  • Guix permet aussi des environnements ad hoc sans fichier, en ne passant que des noms de paquets en ligne de commande, comme guix shell go gopls go-tools
  • guix shell prend en charge --container pour une isolation complète, --emulate-fhs pour exécuter des programmes qui attendent une disposition standard du système de fichiers Linux, et --nesting pour exécuter Guix à l’intérieur d’un conteneur Guix
  • Les manifests Guix sont des fichiers Scheme autonomes, non intégrés dans une structure flake.nix plus large
  • guix shell peut fonctionner sans fichier, alors que nix develop nécessite soit une flake, soit un shell.nix de l’interface historique
  • Flakes fournit des dev shells nommés comme devShells.x86_64-linux.test et devShells.x86_64-linux.default
  • Les manifests Guix, au lieu de proposer des dev shells nommés, reposent sur des fichiers séparés placés côte à côte, comme manifest.scm et test-manifest.scm
  • Nix Flakes et Guix prennent tous deux en charge le développement conteneurisé

Configuration système

  • NixOS et Flakes

    • Dans l’exemple de nixosConfigurations de Flakes, nixpkgs.lib.nixosSystem reçoit une liste de modules NixOS et génère une dérivation système complète incluant le noyau, les services, les fichiers de configuration, etc.
    • La commande d’exemple pour déployer NixOS à partir d’une flake est nixos-rebuild switch --flake .#myhost
    • L’exemple de nixosConfigurations.myhost comprend system = "x86_64-linux"; et modules = [ ./configuration.nix home-manager.nixosModules.home-manager ];
    • Les modules NixOS reposent sur un système de modules qui utilise options, config, mkIf, mkDefault et mkForce avec une fusion basée sur les priorités
    • Le système de modules de NixOS résout les priorités même lorsque plusieurs modules définissent la même option, ce qui facilite l’évitement des conflits même lorsque des dizaines de modules contribuent à une même configuration
  • Guix operating-system

    • Dans Guix, operating-system n’est pas une fonction mais un record Scheme, dont chaque champ est une valeur typée nommée que Guix valide
    • La commande d’exemple pour déployer un système Guix est guix system reconfigure config.scm
    • Le record operating-system d’exemple inclut (host-name "myhost"), (timezone "Etc/UTC"), une configuration de bootloader, des systèmes de fichiers et des services
    • L’exemple de configuration du bootloader Guix utilise grub-efi-bootloader avec la cible "/boot/efi", et Guix prend en charge GRUB, U-Boot, etc.
    • Les systèmes de fichiers Guix sont déclarés sous forme de liste, et %base-file-systems fournit des valeurs par défaut pour /dev, /proc, /sys, etc.
    • Les services Guix forment un graphe orienté acyclique (DAG), et chaque service peut étendre d’autres services
    • %base-services fournit les services essentiels comme le système d’init Shepherd, syslog et le réseau
    • La configuration système Guix n’a pas besoin d’un type de sortie spécial : il suffit d’indiquer à guix system un fichier qui retourne un record operating-system
    • La composition des services dans Guix facilite l’écriture de nouveaux services qui se branchent sur un système existant de manière arbitraire

Découvrabilité et registre

  • Flakes dispose de flake.nix, un point d’entrée standard où sont déclarés dans un seul fichier les dépendances du projet, les sorties et un schéma découvrable
  • Un projet Guix peut utiliser des fichiers conventionnels comme manifest.scm, channels.scm, guix.scm ou package.scm
  • Il existe une volonté de standardiser guix.scm comme fichier de projet reconnu automatiquement par guix shell, mais cela reste moins établi que flake.nix
  • Flakes dispose du registre global flake-registry, qui mappe des noms courts vers des URL ; exemples : nix run nixpkgs#hello, nix build github:NixOS/nixpkgs#firefox
  • Guix utilise des spécifications de paquets pour une commodité similaire, par exemple guix shell hello et guix install firefox
  • Guix n’a pas d’équivalent de registre permettant de désigner un dépôt Git arbitraire par un nom court, et utilise directement les URL
  • Le registre Nix a parfois été source de confusion, car il n’est pas toujours clair si nixpkgs est une entrée du registre, un chemin local ou une autre cible
  • nix flake show est une commande qui affiche sous forme d’arborescence tout ce qu’une flake fournit
  • Guix propose guix search pour les paquets et guix system search pour les services, mais il n’existe pas de commande équivalente pour afficher tout ce qu’un projet ou un dépôt donné fournit ; il faut inspecter directement les fichiers Scheme
  • Flakes est fort en découvrabilité dans la mesure où nix flake show donne une vue cohérente de ce que fournit un projet
  • Les projets Guix sont plus ad hoc : il faut savoir quels fichiers consulter, et il n’existe pas de fichier standard à point d’entrée unique
  • Guix est très flexible, car tout étant en Scheme, on peut définir et combiner ce que l’on veut sans schéma

Modèle de paquets et réécriture de graphe

  • Dans Nix, un paquet est une fonction qui renvoie une derivation via un appel à stdenv.mkDerivation { ... }, et le résultat est un ensemble d’attributs opaque
  • Dans Guix, un paquet est un enregistrement <package>, c’est-à-dire une structure de données transparente avec des champs nommés, que l’on peut inspecter, transformer et combiner avec des procédures Scheme standard
  • Les définitions de paquets de Guix sont des enregistrements transparents plutôt que des fonctions opaques, ce qui permet d’effectuer l’inspection et les transformations de manière programmatique sans outillage spécial
  • Dans Guix, les paquets étant des données, il est facile d’effectuer des réécritures de graphe
  • Dans Guix, package-input-rewriting permet d’exprimer le remplacement de perl par perl-minimal en parcourant l’ensemble du graphe de dépendances
  • Le mot-clé inherit de Guix redéfinit un paquet en héritant de tous les champs de coreutils puis en ne surchargeant que les champs spécifiés
  • Nix dispose d’overlays à visée similaire, mais leur utilisabilité est moindre, car l’inspection et la transformation sont plus difficiles à cause de l’interface en fonctions opaques

Mises à jour de sécurité, bootstrap et authentification

  • Le grafting de Guix permet d’appliquer des mises à jour de sécurité dans l’arbre de dépendances sans reconstruire tous les paquets dépendants
  • Lorsqu’une vulnérabilité touche une bibliothèque bas niveau comme glibc, Guix peut réécrire les chemins du dépôt pour les remplacer par une version corrigée
  • Nix reconstruit tout en cas de mise à jour de sécurité, et sur de grands arbres de dépendances, le temps de build peut différer de plusieurs heures
  • Guix met fortement l’accent sur le bootstrap à partir du code source, ce qui permet de construire l’ensemble du système à partir d’une petite base de confiance
  • La chaîne de bootstrap de Guix commence avec un assembleur hexadécimal d’environ 500 octets, puis passe au compilateur C mes écrit en Scheme, à tcc, puis à l’ensemble de la GNU toolchain
  • Le projet bootstrappable builds traite en détail du bootstrap complet à partir des sources
  • Nix dépend de davantage de graines binaires que Guix
  • Si la chaîne de bootstrap ne peut pas être auditée, on ne peut pas vérifier complètement que le système a bien été construit à partir des sources prévues ; le bootstrap complet à partir des sources est donc important pour la confiance et la vérifiabilité
  • Les channels Guix prennent en charge par défaut une authentification cryptographique
  • Un channel Guix spécifie une « introduction » composée d’un commit précis et de sa signature Ed25519, et Guix vérifie toute la chaîne de signatures depuis cette introduction jusqu’au commit actuel
  • Les Flakes utilisent HTTPS et l’infrastructure GitHub comme modèle de confiance, ce qui constitue un modèle de sécurité différent de l’authentification des channels Guix par Ed25519

Correspondances clés du tableau récapitulatif

  • Pour la déclaration des dépendances, Flakes utilise les inputs de flake.nix, tandis que Guix utilise channels.scm et .guix-channel
  • Pour le verrouillage des dépendances, Flakes utilise flake.lock automatiquement et par projet, tandis que Guix utilise guix describe automatiquement par utilisateur et channels.scm avec spécification manuelle de commits par projet
  • L’évaluation pure est imposée en mode flake, tandis que dans Guix, elle est inhérente à la conception
  • Pour le schéma de sortie, Flakes utilise un attrset structuré dans outputs, tandis que Guix utilise des enregistrements Scheme ad hoc
  • Pour les environnements de développement, Flakes utilisent devShells et nix develop, tandis que Guix utilise manifest.scm et guix shell
  • Pour la configuration système, Flakes utilisent nixosConfigurations et le système de modules, tandis que Guix utilise operating-system et un DAG de services
  • Pour la reproductibilité en une seule commande, Flakes utilisent nix build github:foo/bar, tandis que Guix utilise la forme guix time-machine -C channels.scm -- build
  • Pour le verrouillage par projet, Flakes le gèrent automatiquement avec flake.lock, tandis que Guix le gère manuellement avec channels.scm contenant les commits
  • Pour l’explorabilité, Flakes utilisent nix flake show, tandis que Guix s’appuie sur l’inspection des modules Scheme
  • Pour le modèle de paquets, Flakes/Nix utilisent des fonctions opaques, tandis que Guix utilise des enregistrements transparents
  • Pour l’init system, Nix utilise systemd, tandis que Guix utilise GNU Shepherd
  • Pour les mises à jour de sécurité, Nix reconstruit tout, tandis que Guix utilise un grafting rapide
  • Pour la confiance dans le bootstrap, Nix repose sur des graines binaires, tandis que Guix repose sur un bootstrap complet à partir des sources
  • Pour les mises à jour authentifiées, Flakes reposent sur la confiance dans HTTPS/GitHub, tandis que Guix utilise l’authentification des channels par Ed25519
  • Pour la prise en charge de la FHS, Nix propose buildFHSUserEnv, tandis que Guix propose --emulate-fhs
  • Pour la prise en charge hors Linux, Nix propose nix-darwin pour macOS, tandis que Guix est structuré autour de GNU Hurd
  • Concernant l’exclusivité au logiciel libre, Nix n’est pas exclusivement libre et peut être configuré, tandis que Guix respecte les FSDG

Conclusion

  • Flakes et Guix résolvent le même type de problèmes — reproductibilité, gestion des dépendances et déclaration du système — avec des philosophies d’architecture différentes
  • Flakes se rapproche d’une fonctionnalité unique avec un fichier, un schéma, un fichier de verrouillage et un ensemble de conventions
  • Guix est une combinaison d’outils orthogonaux comme les channels pour la distribution, les manifests pour les environnements, operating-system pour la configuration, guix time-machine pour la reproductibilité, et les enregistrements Scheme pour d’autres structures
  • Si l’on préfère une seule manière standard, un seul fichier d’entrée, un seul schéma de sortie et un seul format de verrouillage, Flakes est un choix naturel
  • Si l’on préfère une approche qui applique à la gestion de paquets la philosophie Unix consistant à combiner de petits outils indépendants dont chacun fait bien une chose, Guix convient bien
  • Les deux écosystèmes se sont développés autour de l’idée que la gestion de paquets doit être fonctionnelle, déclarative et reproductible, et poussent cette même idée avec des implémentations différentes

1 commentaires

 
GN⁺ 5 시간 전
Avis sur Lobste.rs
  • Ce site est beaucoup trop pénible à lire sur mobile : le texte est un peu petit, et il interrompt sans arrêt au moindre défilement
    Après la première comparaison, je n’arrivais plus à lire, parce que ça remontait sans cesse à la table des matières

    • C’est carrément illisible. Ça bouge comme un yoyo. C’était l’un des articles que j’avais le plus envie de lire récemment, donc je suis déçu par une expérience de lecture extrêmement frustrante
    • Même problème sur desktop. C’est absurde, on dirait presque que l’accessibilité a été sabotée volontairement
  • Même après avoir lu l’article, je ne comprends toujours pas très bien comment on est censé spécifier et figer les dépendances d’un projet. Pour le déployer et le partager, on dirait qu’il faut retrouver manuellement le hash de commit de chaque dépendance transitive et le mettre dans channels.scm
    time-machine semble ne fonctionner que sur l’ensemble de paquets Guix, pas sur les dépendances hors arborescence
    Avec Nix, on peut aussi exécuter assez facilement l’état passé de nixpkgs avec quelque chose comme nix run github:nixos/nixpkgs/<commit hash>#<package>
    Ce qui est particulier avec Guix, c’est qu’il ne sépare pas la version de la collection de paquets de la version du gestionnaire de paquets. Si on veut exécuter un ancien paquet, on finit aussi par lancer une ancienne version de Guix, et je ne vois pas bien pourquoi on voudrait ça
    L’article dit que les flakes obligent à retrouver les commits manuellement, puis juste après il donne en exemple une commande Guix où il faut justement préciser un commit. On peut aussi remplacer la version de nixpkgs dans un Nix flake avec --override-input, mais c’est assez sale, et c’est d’ailleurs un des points qu’unflake essaie d’améliorer

    • J’ai moins d’expérience avec Guix que l’auteur, mais j’ai tout de même lu pas mal de documentation, donc je vais essayer de répondre à quelques points
      En général, on développe dans un environnement guix shell dédié, puis quand vient le moment de partager, on enregistre tous les hashes de commit dans channels.scm avec guix describe -f channels > channels.scm
      Dans la doc declaring channel dependencies, on voit qu’on peut préciser les commits des dépendances, mais il ne semble pas y avoir d’option pour vérifier qu’une dépendance qui dépend elle-même d’autre chose est bien figée sur des commits précis elle aussi
      La notation --commit= de time-machine correspond à un canal Guix, mais on peut aussi charger des canaux supplémentaires depuis un fichier avec -C
      Cela a l’avantage de ne pas perdre l’historique ni la reproductibilité même quand il y a des changements incompatibles dans le gestionnaire de paquets et les enregistrements de paquets
    • On pourrait faire ça en construisant un index inversé de nixpkgs : par exemple, que les commits X à Y de nixpkgs contiennent la version A d’un paquet donné
      En revanche, cela demande un checkout de nixpkgs pour chaque commit, donc le coût initial de construction serait énorme. Une fois l’index créé, le coût pour le maintenir serait faible
  • J’ai signalé le problème du site et ce fil à coopi, donc j’espère que ce sera corrigé bientôt
    Même si je penche complètement du côté de Guix, j’aimerais bien, comme le dit coopi, que Guix ait lui aussi un fichier/répertoire standard comme flake.nix ou un répertoire nix qui contienne tout. Cela dit, comme il faut indiquer le bon chemin pour importer les modules Scheme, ce n’est peut-être pas possible
    Ce post Lobsters contient bien ce dont parle l’auteur, donc les tags nix et lisp me semblent suffisants

    • Je ne suis pas convaincu par l’idée d’enlever linux. C’est le seul noyau qu’ils ont en commun tous les deux :P En revanche, comme tu le dis, unix n’est probablement pas pertinent
    • Ce serait bien aussi d’avoir un type de données de canal structuré qui aide à déduire automatiquement ce qu’un canal fournit, un peu comme les flakes
      Par exemple, quelque chose comme ça :
      (channel  
        (operating-systems  
          (list my-vm))  
        (services  
          (list my-system-service)))  
      
      Et ce serait bien d’avoir aussi une commande guix channel pour faciliter la création et la gestion de nouveaux canaux
  • Je me demande si Guix a aussi une fonctionnalité comme .inputs.nixpkgs.follows dans les Nix flakes, pour remplacer le figement des dépendances transitives
    Et une bonne partie de la description de Guix par l’auteur fait penser au Nix d’avant les flakes : pas de point d’entrée standard, usage de canaux, etc. Cela dit, avec Guix, le système de formats et le fait d’avoir un vrai langage rendent ce genre de schéma moins pénible. On dirait une histoire alternative de ce qu’aurait pu être Nix s’il avait été meilleur, ou écrit dans un autre langage

    • À quoi sert exactement cette fonctionnalité ?
  • À cause des problèmes d’ergonomie signalés dans d’autres commentaires, j’hésite à recommander l’article. Comme j’utilise NoScript avec JavaScript désactivé par défaut, je ne m’en étais pas rendu compte
    Cela dit, ce texte arrive au bon moment. Dans mon entreprise, on s’oriente vers un usage massif de Nix, et on galère un peu avec les flakes ; les explications ici m’ont semblé bien plus claires que tout ce que j’avais lu auparavant

    • D’après Coopi, il avait essayé de suivre le principe d’amélioration progressive pour que le site reste lisible sans JavaScript ni CSS ; la partie JavaScript a été ratée, mais au moins cette philosophie fonctionnait. À présent, le JavaScript devrait être corrigé lui aussi
  • Réponse de Coopi : il a fait une modification ce matin, mais n’a pas pu la tester à cause du travail, et il s’est avéré qu’il y avait un problème dans le JavaScript

  • Ce site est inutilisable sur mobile iOS. On dirait que la page se charge en bas puis remonte immédiatement vers le haut, et dès que je descends de plus d’un écran, quelque chose se déclenche et me remonte encore
    Le mode lecture fonctionne, mais on perd la mise en évidence et les détails de style qui étaient pourtant plutôt réussis

  • Il est juste de dire que ce que font les Nix flakes peut aussi se faire avec plusieurs outils Guix, mais il faut aussi rappeler que Nix avait déjà, et a toujours, de petits outils orthogonaux pour résoudre les mêmes problèmes
    Ce que les flakes apportent, c’est un point d’entrée standard pour les projets et l’écosystème que cela rend possible, par exemple le registre. L’article dit d’ailleurs que Guix n’a pas cet équivalent
    Les utilisateurs de Guix peuvent considérer qu’un point d’entrée standard n’est pas nécessaire, et beaucoup d’utilisateurs de Nix l’ont pensé aussi
    Mais dire qu’on peut faire des flakes avec un ensemble d’outils orthogonaux, c’est un peu comme dire que FreeBSD n’a pas besoin de support OCI puisque les jails permettent déjà de tout faire. Cela passe à côté du fait que la standardisation rend possible tout un écosystème
    Je m’intéresse beaucoup à Guix et j’y ai même un peu contribué, mais j’aimerais comparer pourquoi construire avec guix time-machine et channels.scm prend tellement plus de temps que modifier le verrouillage d’un flake puis évaluer Nix. Si c’était juste trois fois plus lent — par exemple passer de 5–10 secondes à 15–30 secondes — je pourrais l’accepter, mais ce n’est pas du tout l’impression que j’ai eue en essayant