Depuis 2 ans, j’utilise Nix à toutes ses sauces : NixOS en distribution personnelle, Nix sur la machine Ubuntu à mon travail, et home-manager en tant que gestionnaire de configuration de mes dotfiles. Et si j’adore la communauté de Nix et que je n’hésite pas à faire mes petites PRs sur le registre officiel : je n’en reste pas moins déçu que Nix soit seul sur le trône.

Parce que Nix possède un concurrent bien moins connu : Guix.

Guix est comparable à Nix dans de nombreux points:

  • C’est avant tout un gestionnaire de paquet.
  • Il possède une distribution depuis laquelle vous pourrez tout gérer en Scheme.

Remarque

La première version de Guix était elle-même basée sur Nix en rajoutant le support du Scheme.

Et pourquoi chercher une alternative à Nix ? Parce que le Haskell n’est pas un langage très courant et que Scheme est bien plus accessible. Guix est plus récent et possède donc une communauté plus petite et moins active mais cela ne veut pas dire que Guix est moins bon que Nix !

Cette page est donc une légère introduction à Guix, pour vous montrer comment l’installer et l’utiliser dans l’espoir de vous donner envie de l’essayer.

Installer Guix

2 options s’offrent à vous :

  • L’installeur par script :
cd /tmp
wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
chmod +x guix-install.sh
./guix-install.sh
  • Passer par APT si vous êtes sous Debian :
apt install guix

Permettre à un utilisateur d’utiliser Guix

Chaque utilisateur possède son gnu-store (équivalent de nix-store) qui fera office de PATH pour vos binaires installés via Guix.

Pour que Guix accepte qu’un utilisateur ait son propre store, il faut créer le dossier accueillant les profiles de ce dit utilisateur.

sudo mkdir /var/guix/profiles/per-user/$USER
sudo chown $(id -u):$(id -g) /var/guix/profiles/per-user/$USER

Utiliser un proxy dans Guix

Au travail, j’ai un proxy qui me permet d’accéder à internet.

Guix ne va pas lui-même chercher les variables HTTP_PROXY dans votre session. Celles-ci doivent être configurées dans le service guix-daemon géré par Systemd.

Pour cela, il faut modifier le service en ajoutant les variables d’environnements.

# sudo vim /etc/systemd/system/guix-daemon.service
...
[Service]
ExecStart=/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
    --build-users-group=guixbuild --discover=no
Environment='GUIX_LOCPATH=/var/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8
Environment='HTTP_PROXY=http://squid-server:3128'
Environment='HTTPS_PROXY=http://squid-server:3128'
Environment='http_proxy=http://squid-server:3128'
Environment='https_proxy=http://squid-server:3128'
StandardOutput=syslog
StandardError=syslog
...

Source

Commandes simples

Nous sommes avec notre utilisateur personnel, notre proxy (si besoin) est configuré, nous pouvons enfin commencer à jouer avec Guix !

➜  guix install hello
Le paquet suivant sera installé :
   hello 2.12.1

substitute: mise à jour des substituts depuis « https://ci.guix.gnu.org »... 100.0 %
La dérivation suivante sera compilée :
  /gnu/store/kljd0jwzfj67k5l8klhaf8ahn6gyd46v-profile.drv

0,1 Mo seront téléchargés
 hello-2.12.1  59KiB                                                                                                                                                     216KiB/s 00:00 ▕██████████████████▏ 100.0%
construction de l'ensemble des certificats des AC…
énumération des sous-répertoires Emacs…
construction du répertoire des polices…
génération du cache des chargeurs GdkPixbuf…
génération du cache de schémas GLib…
création du cache des thèmes d'icônes GTK+…
construction des fichiers de cache pour les méthodes d'entrée GTK+…
construction du répertoire des manuels Info…
construction du cache des fichiers desktop du XDG…
construction de la base de données MIME du XDG…
construction du profil avec 3 paquets…

Ajoutez ensuite le dossier ”~/.guix-profile/bin” à votre PATH:

export PATH:$PATH:$HOME/.guix-profile/bin

Maintenant, nous allons constater plusieurs choses…

➜ which hello
/home/quentin/.guix-profile/bin/hello
➜ ll /home/quentin/.guix-profile/bin/hello
lrwxrwxrwx 1 root root 66 janv.  1  1970 /home/quentin/.guix-profile/bin/hello -> /gnu/store/5mqwac3zshjjn1ig82s12rbi7whqm4n8-hello-2.12.1/bin/hello
  • Chaque binaire est stocké dans le gnu-store à au répertoire suivant: /gnu/store/HASH-nom-version/bin
  • Il n’est pas necéssaire d’être root pour installer un package.
  • Chaque utilisateur possède ses propres executables.

Remarque

Le Hash correspond aux hashs de toutes les dépendances utilisées pour construire le paquet final.

➜  root ~ guix package --list-installed
hello   2.12.1  out     /gnu/store/s5pd3rnzymliafb4la5sca63j86xs0y0-hello-2.12.1
root@workstation:/gnu/store# déconnexion
➜  quentin ~ guix package --list-installed
git     2.38.1  out     /gnu/store/h7bnbhkfsdcjsyd3g24www00z4w9a4vh-git-2.38.1
geany   1.38    out     /gnu/store/16hzgav08xkcfy15pmhm2ynijyp8y2k1-geany-1.38
hello   2.12.1  out     /gnu/store/5mqwac3zshjjn1ig82s12rbi7whqm4n8-hello-2.12.1

Pour supprimer un programme:

➜  guix remove hello

Les générations

Chaque fois que vous installez ou supprimez un programme, vous créez une ‘génération’. Ce sont des checkpoints avec lesquelles vous pouvez revenir à une configuration antérieure.

guix package --list-generations
guix package --switch-generation
guix package --roll-back

Les générations se suppriment avec le Garbage Collector qui supprime les restes des précédentes générations ainsi que les dépendances inutilisées. La documentation recommande de le lancer périodiquement ou lorsque vous n’avez plus beaucoup d’espace libre disponible.

guix gc -F 5G # Libère de la place jusqu'à obtenir minimum 5Go de libre
guix gc -d 5m # Supprime les générations datant de +5 mois.

Exemple :

#guix gc -d 2h 
suppression de /var/guix/profiles/per-user/quentin/guix-profile-1-link
suppression de /var/guix/profiles/per-user/quentin/guix-profile-2-link
finding garbage collector roots...
deleting garbage...
[0 MiB] deleting '/gnu/store/ldy29j64j9lwj3snbxc9wrrb8j5fjs4n-profile.drv'
[0 MiB] deleting '/gnu/store/004nbl5lph6wxn3w11rajsmq5yihcj2b-emacs-subdirs.drv'
[0 MiB] deleting '/gnu/store/2kji3jh7qkm04xmfzmpfmrk7829q1kdr-emacs-subdirs-builder'
[0 MiB] deleting '/gnu/store/2dbqni9zbq6vp4g63baiwr4n4wbw7bx3-profile.drv'
[0 MiB] deleting '/gnu/store/7bydrw628jfhi36nca8vphi8i36krw81-profile-builder'
[0 MiB] deleting '/gnu/store/w6vvnjc26a1axxdwbdlanjrb1hwada5w-profile'
[0 MiB] deleting '/gnu/store/zayyazzxbv6qhchbl8lzr4pbf11312gs-vim-9.0.0954'
[30 MiB] deleting '/gnu/store/55q02v1a3qz8n7rlhy3jva9qjkfwj8y0-gawk-5.1.0'
[33 MiB] deleting '/gnu/store/4r6f3a6n82nv48c7nznhhcl19k7pl0ig-libsigsegv-2.13'
[33 MiB] deleting '/gnu/store/2p7w48cngcmfjmyy7ycfnckpsf8mysff-fonts-dir.drv'
[33 MiB] deleting '/gnu/store/8y1wfxlar067j2zs6aflcib13jbss16w-ca-certificate-bundle.drv'
[33 MiB] deleting '/gnu/store/bpl0lv73y37by4zfzsvbb3c86ay9svpq-info-dir.drv'
[33 MiB] deleting '/gnu/store/pfpa2yfi69d854hykgpixqx60mjgnwlq-vim-9.0.0954.drv'
[33 MiB] deleting '/gnu/store/b5f9v9crmmcxaw8m1m92ar546l40kdk6-gawk-5.1.0.drv'
[33 MiB] deleting '/gnu/store/c4mv0jafqjbi0bzymlw4gxkf9pkp6w35-libsigsegv-2.13.drv'
[33 MiB] deleting '/gnu/store/q6a1xlvdlbca6p141vxfm91hqmb3bpql-fonts-dir-builder'
[33 MiB] deleting '/gnu/store/4ifl3xdlsyp8yn6d5ds9wz0aw51y84h9-ca-certificate-bundle-builder'
[33 MiB] deleting '/gnu/store/i0lgqasdnzi3azbfni100snrrrz18hpk-profile'
[33 MiB] deleting '/gnu/store/jkmj2cxmjbmn69v2cl32sfbyf3lkdh45-guix.vim'
[33 MiB] deleting '/gnu/store/d99ykvj3axzzidygsmdmzxah4lvxd6hw-bash-5.1.8'
[39 MiB] deleting '/gnu/store/z7qsw2d6viyyh3lb73lrmb5fmx6q5m2l-profile-builder'
[39 MiB] deleting '/gnu/store/ii91b2jkcfhzp29hzyhk47c5vzqvcsga-vim-9.0.0954-builder'
[39 MiB] deleting '/gnu/store/2jnvcisk16p80iafkgkksr1r8wfhwp13-emacs-subdirs'
[39 MiB] deleting '/gnu/store/126wzabjb75fazzh5rr5yszvi69gpxp7-vim-9.0.0954-checkout.drv'
[39 MiB] deleting '/gnu/store/mwgfj5ffvk3kp937cv0czypl0qi419vc-libsigsegv-2.13-builder'
[39 MiB] deleting '/gnu/store/0yfxwncikjrl4hyam1bh0mnrvgxszncg-gawk-5.1.0-builder'
[39 MiB] deleting '/gnu/store/h5w8rr8bb1949njxw69pi7lj61vqbvg2-info-dir'
[39 MiB] deleting '/gnu/store/018vla0va6vv1af7zvpb8j0vzqixhlkd-info-dir-builder'
[39 MiB] deleting '/gnu/store/x19qf193mrih69y0cc8gyjnbsyh0vhwd-tcsh-6.22.03'
deleting `/gnu/store/trash'
deleting unused links...
note: currently hard linking saves 403.70 MiB
guix gc: 75,62 Mio libérés

Avertissement

Il n’est pas toujours utile de lancer le GC. Les dépendances sont souvent réutilisables et vous évitent de re-télécharger les mêmes librairies.

Lancer un environnement éphémère

Comme Nix avec nix-shell, Guix permet de lancer un environnement éphémère avec les paquets que vous souhaitez. Cela permet de tester un paquet sans l’installer sur votre système ou de lancer un environnement avec des paquets pour un projet spécifique.

kiko@guix:~/src/home$ hello
-bash: hello : commande introuvable
kiko@guix:~/src/home$ guix shell --container hello
substitute: mise à jour des substituts depuis « https://ci.guix.gnu.org »... 100.0 %
La dérivation suivante sera compilée :
  /gnu/store/sr0466p3s6h3gnwkcyc03vgfbgvk2ihx-profile.drv

0,1 Mo seront téléchargés
 hello-2.12.1  59KiB                                                                                                                                                                                                650KiB/s 00:00 [##################] 100.0%
construction de l'ensemble des certificats des AC…
énumération des sous-répertoires Emacs…
construction du répertoire des polices…
construction du répertoire des manuels Info…
construction du profil avec 1 paquet…
kiko@guix ~/src/home [env]$ hello
Hello, world!
kiko@guix ~/src/home [env]$ 

Gérer ses dotfiles avec Guix

Guix possède un module dédié à la gestion de vos dotfiles. Il est très simple à utiliser et permet de gérer vos dotfiles avec un seul fichier de configuration. Celui-ci est une alternative à Home-Manager de Nix.

Nous allons donc découvrir guix home.


à la différence de Home-Manager (nix), guix home ne demande pas à ce que vous déposiez vos fichiers de configuration dans un dossier spécifique. Libre à vous de les mettre où vous voulez.

mkdir -p ~/src/home
cd ~/src/home

Nous allons initialiser notre configuration avec un fichier home-configuration.scm:

(use-modules (gnu home))

(home-environment
   (packages (list))
    (services (list)))

En résumé : nous allons créer un environnement avec 0 paquet et 0 service.

Pour tester notre configuration, nous allons pouvons lancer un shell temporaire avec notre environnement :

# guix home container home-configuration.scm 
WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
Symlinking /home/kiko/.profile -> /gnu/store/dann7r1095xll0kji5yl0ql07096rc8j-shell-profile... done
Symlinking /home/kiko/.config/fontconfig/fonts.conf -> /gnu/store/4261pxafny0g2myhh9yj1771ry7k05lc-fonts.conf... done
 done
Finished updating symlinks.

Comparing /gnu/store/non-existing-generation/profile/share/fonts and
          /gnu/store/7cyscgadpsb47vblb5qlzrnjd8cwq8zk-home/profile/share/fonts... done (same)
Evaluating on-change gexps.

On-change gexps evaluation finished.

warning: XDG_RUNTIME_DIR doesn't exists, on-first-login script
won't execute anything.  You can check if xdg runtime directory exists,
XDG_RUNTIME_DIR variable is set to appropriate value and manually execute the
script by running '$HOME/.guix-home/on-first-login'-bash-5.1$ 
-bash-5.1$ echo "Hello World"

Si vous ne souhaitez pas partir d’une configuration vide, vous pouvez utiliser la commande guix home import . qui va créer le fichier home-configuration.scm en complétant les champs packages et services avec les paquets et services déjà installés sur votre système.

Par défaut, il copie aussi les fichiers de configuration Bash.

ls -a
.  ..  .bash_logout  .bashrc  home-configuration.scm
;; Ce fichier « home-environment » peut être passé à « guix home reconfigure » pour reproduire
;; le contenu de votre profil. Son contenu est « symbolique » : il ne spécifie que les
;; noms des paquets. Pour reproduire exactement le même profil, vous devez aussi
;; retenir les canaux utilisés, ceux renvoyés par « guix describe ».
;; Voir la section « Répliquer Guix » dans le manuel.

(use-modules (gnu home)
             (gnu packages)
             (gnu services)
             (guix gexp)
             (gnu home services shells))

(home-environment
  ;; Ci-dessous se trouve la liste des paquets qui seront disponibles dans votre
  ;; profil personnel, dans ~/.guix-home/profile.
  (packages (specifications->packages (list "git")))

  ;; Voici la liste des services personnels.  Pour trouver les services disponibles,
  ;; lancez « guix home search MOT-CLÉ » dans un terminal.
  (services
   (list (service home-bash-service-type
                  (home-bash-configuration
                   (aliases '(("ls" . "ls --color=auto")))
                   (bashrc (list (local-file "./.bashrc" "bashrc")))
                   (bash-logout (list (local-file "./.bash_logout"
                                                  "bash_logout"))))))))

Ce code montre qu’il est possible de paramétrer son bashrc à partir du Scheme (aliases '(("ls" . "ls --color=auto"))) et ajouter le contenu d’un fichier local (bashrc (list (local-file "./.bashrc" "bashrc"))).

Une fois satisfait de votre configuration, vous pouvez l’appliquer avec la commande guix home reconfigure home-configuration.scm.

Conclusion

Guix me semble une alternative très intéressante à Nix. Le Scheme est un langage très accessible et permet de créer des configurations très facilement. Je pense que je vais continuer à utiliser Guix pour des projets personnels et peut-être même pour mes dotfiles.

Je reparlerai de Guix dans un prochain article lorsque je serai plus à l’aise avec celui-ci.

Si vous souhaitez en savoir plus sur Guix, je vous conseille de lire le manuel.

Liens en vrac