Posted on July 17, 2018

I wanted to run Guix on a NixOS machine. Even though the Guix manual explains how to do it step by step, I needed a few extra ones to make it work properly.

I couldn’t just install GuixSD because my wireless network card doesn’t have any free/libre drivers (yet).

Creating guixbuilder users

Guix requires you to create non-root users that will be used to perform the builds in the isolated environments.

The manual already provides you with a ready to run (as root) command for creating the build users:

1 2 3 4 5 6 7 8 groupadd --system guixbuild for i in ` seq -w 1 10 ` ; do useradd -g guixbuild -G guixbuild \ -d /var/empty -s ` which nologin ` \ -c "Guix build user $i " --system \ guixbuilder $i ; done

However, In my personal NixOS I have disabled users.mutableUsers , which means that even if I run the above command it means that they’ll be removed once I rebuild my OS:

1 2 3 4 5 6 7 8 9 10 11 12 13 $ sudo nixos-rebuild switch ( ... ) removing user ‘guixbuilder7’ removing user ‘guixbuilder3’ removing user ‘guixbuilder10’ removing user ‘guixbuilder1’ removing user ‘guixbuilder6’ removing user ‘guixbuilder9’ removing user ‘guixbuilder4’ removing user ‘guixbuilder2’ removing user ‘guixbuilder8’ removing user ‘guixbuilder5’ ( ... )

Instead of enabling users.mutableUsers I could add the Guix users by adding them to my system configuration:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 { config , pkgs , ... }: { # ... NixOS usual config ellided ... users = { mutableUsers = false ; extraUsers = let andrehUser = { andreh = { # my custom user config }; }; buildUser = ( i : { "guixbuilder ${ i } " = { # guixbuilder$i group = "guixbuild" ; # -g guixbuild extraGroups = [ "guixbuild" ]; # -G guixbuild home = "/var/empty" ; # -d /var/empty shell = pkgs . nologin ; # -s `which nologin` description = "Guix build user ${ i } " ; # -c "Guix buid user $i" isSystemUser = true ; # --system }; } ); in # merge all users pkgs . lib . fold ( str : acc : acc // buildUser str ) andrehUser # for i in `seq -w 1 10` ( map ( pkgs . lib . fixedWidthNumber 2 ) ( builtins . genList ( n : n + 1 ) 10 )); extraGroups . guixbuild = { name = "guixbuild" ; }; }; }

Here I used fold and the // operator to merge all of the configuration sets into a single extraUsers value.

Creating the systemd service

One other thing missing was the systemd service.

First I couldn’t just copy the .service file to /etc since in NixOS that folder isn’t writable. But also I wanted the service to be better integrated with the OS.

That was a little easier than creating the users, all I had to do was translate the provided guix-daemon.service.in configuration to an equivalent Nix expression

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # This is a "service unit file" for the systemd init system to launch # 'guix-daemon'. Drop it in /etc/systemd/system or similar to have # 'guix-daemon' automatically started. [Unit] Description = Build daemon for GNU Guix [Service] ExecStart = /var/guix/profiles/per-user/root/guix-profile/bin/guix-daemon --build-users-group=guixbuild Environment = GUIX_LOCPATH=/root/.guix-profile/lib/locale RemainAfterExit = yes StandardOutput = syslog StandardError = syslog # See <https://lists.gnu.org/archive/html/guix-devel/2016-04/msg00608.html>. # Some package builds (for example, go@1.8.1) may require even more than # 1024 tasks. TasksMax = 8192 [Install] WantedBy = multi-user.target

This sample systemd configuration file became:

1 2 3 4 5 6 7 8 9 10 11 12 13 guix-daemon = { enable = true ; description = "Build daemon for GNU Guix" ; serviceConfig = { ExecStart = "/var/guix/profiles/per-user/root/guix-profile/bin/guix-daemon --build-users-group=guixbuild" ; Environment = "GUIX_LOCPATH=/root/.guix-profile/lib/locale" ; RemainAfterExit = "yes" ; StandardOutput = "syslog" ; StandardError = "syslog" ; TaskMax = "8192" ; }; wantedBy = [ "multi-user.target" ]; };

There you go! After running sudo nixos-rebuild switch I could get Guix up and running:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ guix package -i hello The following package will be installed: hello 2.10 /gnu/store/bihfrh609gkxb9dp7n96wlpigiv3krfy-hello-2.10 substitute: updating substitutes from 'https://mirror.hydra.gnu.org' ... 100.0% The following derivations will be built: /gnu/store/nznmdn6inpwxnlkrasydmda4s2vsp9hg-profile.drv /gnu/store/vibqrvw4c8lacxjrkqyzqsdrmckv77kq-fonts-dir.drv /gnu/store/hi8alg7wi0wgfdi3rn8cpp37zhx8ykf3-info-dir.drv /gnu/store/cvkbp378cvfjikz7mjymhrimv7j12p0i-ca-certificate-bundle.drv /gnu/store/d62fvxymnp95rzahhmhf456bsf0xg1c6-manual-database.drv Creating manual page database... 1 entries processed in 0.0 s 2 packages in profile $ hello Hello, world!

Some improvements to this approach are:

looking into NixOS modules and trying to bundle everything together into a single logical unit; build Guix from source and share the Nix store and daemon with Guix.

Happy Guix/Nix hacking!