Recently I've been using Guix to run the latest versions of applications on top of Ubuntu. Guix is an advanced package manager that has a rolling release and advanced capabilities like transactions. This gives me the advantage of Ubuntu's hardware testing and QA for the core [1] , while also being able to use the latest versions of applications through Guix. It also means I can minimise Flatpak/Snap packages which I find inelegant and annoying. This post covers some of the benefits of Guix and covers basic usage.
The first thing to know is that Guix is both a package manager and an entire Linux [2] distribution. I'm using it as a package manager on top of Ubuntu (22.04 LTS). Guix is worth considering if you want:
Unsurprisingly there are trade-offs in this approach that are worth knowing about:
Wow, that section is a lot longer than I was expecting! Lets get to installing Guix. Rather than installing on our main machine I'm going to cover how to install it in a container/VM on Ubuntu 22.04 LTS. That way we can play around with it without any risk to our main system.
On Ubuntu the system containers (LXC/LXD) capabilities are installed by default so it's easy to get started. In this example my main machine is called ``dev-host``, and the container instance we'll install Guix inside is called ``guix-host1`` - the prompt shows where we're running the command.
Lets first start by checking that we're on LXD 5.0 or greater. If you haven't used LXD then you'll need to init it:
dev-host:$ snap info lxd [lots of output] tracking: 5.0/stable/ubuntu-22.04 [lots of output] dev-host:$ lxd init
I'm not going to cover how to configure LXD, if you accept the defaults it should work. If you're stuck there's lots of great information on the LXD forums and in the documentation.
As we noted above Guix uses a lot of disk space, so make sure that the LXD storage pool is pointing to a location where there's plenty of available space.
dev-host:$ lxc storage list
We're now ready to start our container instance.
# check that the user is in the lxd group dev-host:$ groups <user> adm cdrom sudo dip plugdev lxd # list the available ubuntu images dev-host:$ lxc image list images: ubuntu # create a container instance called guix-host1 dev-host:$ lxc launch ubuntu:22.04 guix-host1 # check that it's now running dev-host:$ lxc list
At this point we have a container instance (guix-host1) running, so we now need to connect to it.
We could just install Guix using the root user in the container, but that would be a very realistic test of how it would work on a normal host. We'll create a normal user and SSH into the container as if it was a remote host.
# connect to the container instance dev-host:$ lxc shell guix-host1 # remove the default ubuntu user and add our normal username # we also want this user to be able to do sudo commands root@guix-host1:# deluser ubuntu root@guix-host1:# adduser <username> root@guix-host1:# usermod -aG sudo <username>
We install the SSH server and set-up our users .ssh directory so we can copy the public key in.
root@guix-host1:# apt install openssh-server -y # edit /etc/ssh/sshd_config and allow PubkeyAuthentication PubkeyAuthentication yes # restart the SSHD server root@guix-host1:# sudo systemctl restart ssh.service # create the ssh config directory for our normal user root@guix-host1:# su <username> user@guix-host1:$ mkdir /home/<username>/.ssh # Disconnect from the LXC instance user@guix-host1:$ exit
The next step is to push the key to the container instance.
dev-host:$ lxc file push ~.ssh/id_rsa.pub guix-host1/home/steve/.ssh/authorised_keys
At this point you should be able to SSH into the container using the IP address that shows when running lxc ls.
It's a bit annoying using the IP address, so we'll set up name resolution so we can use the containers name to SSH into it:
# check the IP address and range that the bridged network is using dev-host:$ lxc network get lxdbr0 ipv4.address 10.233.50.1/24 dev-host:$ lxd network get lxdbr0 dns.domain
The default is for LXD to set-up a bridged network (lxdbr0) so we check this to see the IP address and whether it has a domain associated (none by default). We can then tell systemd-resolvd about it by doing the following:
dev-host:$ sudo resolvectl dns lxdbr0 10.233.50.1 dev-host:$ sudo resolvectl domain lxdbr0 '~lxd' # if we've been successful we can now do name resolution dev-host:$ ping guix-host1.lxd
That was a lot of steps, but now the system container is ready and we can install Guix.
To install the Guix package manager go to their download area and grab the right binary: for me that is GNU Guix 1.3.0 Binary. It's worth reading through their installation instructions to make sure nothing has changed.
The installer is fairly straightforward it will ask some basic questions and then set-up the Guix build daemon.
# ssh into the guix container dev-host:$ ssh guix-host1.lxd user@guix-host1:$ cd /tmp user@guix-host1:$ wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh user@guix-host1:$ chmod +x guix-install.sh # run the installer user@guix-host1:$ sudo /tmp/guix-install.sh # restart the guix daemon user@guix-host1:$ sudo systemctl status guix-daemon.service
It's worth knowing that the way Guix works is to run a single build daemon on the host which has a store with all the packages in it that have been build/downloaded onto this host. Each time a user runs a command they're interacting with this store via the daemon..
The Guix installer configures the users shell with a default profile, this is stored in $GUIX_PROFILE. Disconnect and reconnect to the container to check that the environment variables are being sourced correctly.
# check env vars are being sourced user@guix-host1:$ exit dev-host:$ ssh guix-host1.lxd user@guix-host1:$ echo $GUIX_PROFILE /home/<username>/.guix-profile # check that the GUIX command is part of PATH user@guix-host1$ guix show hello [output with information about the hello package]
Guix requires the ability to write to the /gnu/store directory, but this is not allowed by a system container normally. If you try to do any command that writes to the package store it will error:
user@guix-host1$ guix install hello guix install: error: remounting /gnu/store writeable: Permission denied
We can allow the container to write to /gnu/store by removing the confines that the AppArmor profile has on it: there's probably an elegant way to do this where you just allow it to write to /gnu/store, but this works!
user@guix-host1$ exit # on our dev host we stop the container and edit the configuration dev-host:$ lxc stop guix-host1 dev-host:$ lxc config set guix-host1 raw.lxc "lxc.apparmor.profile=unconfined" dev-host:$ guix start guix-host1 dev-host:$ ssh guix-host1.lxd
Before we start playing with Guix we need to install a locale which the Guix build daemon can use. If we don't do this it leaves an annoying error in the systemctl status message: although I don't think it's actually harmful.
# install the locales into the root users default profile user@guix-host1:$ sudo -i guix install glibc-locales user@guix-host1:$ sudo systemctl restart guix-daemon.service user@guix-host1:$ sudo systemctl status guix-daemon.service
The same thing applies for the normal user, Guix needs to know the locale that it's using.
user@guix-host1:$ guix install glibc-locales user@guix-host1:$ localectl set-locale en_GB.UTF-8
As I'm using GB English I set it to en_GB.UTF-8, if you're not sure what it should be you can check how it's configured on your main machine. To check that it's actually worked disconnect and reconnect to the container:
user@guix-host1: exit dev-host:$ ssh guix-host1.lxd # If the Guix Locale path is configured we're all set user@guix-host1:$ echo $GUIX_LOCPATH /home/<user>/.guix-profile/lib/locale
I have no idea what NSCD does, and can find some content saying that it can cause problems. However, the Guix manual has a section for Application Set-up which says it should be installed.
user@guix-host1:$ sudo apt install nscd
The version of the Guix daemon that we installed is probably out of date compared to the latest version in the repository and consequently the commands that Guix understands. The build daemon runs the guix command that is installed by the root user. So to update the daemon we update roots guix package definitions.
user@guix-host1:$ sudo -i guix pull [this will take a while as it downloads the updated repository] user@guix-host1:$ sudo systemctl restart guix-daemon.service user@guix-hsot1:$ sudo systemctl status guix-daemon.service
Now we need to update the package list for our normal user and upgrade any packages we've installed. We do this with:
# see which packages we have installed - should be just glibc-locales user@guix-host1:$ guix package --list-installed glibc-locales 2.33 out /gnu/store/ixzmi6614baf4w37qfjgqrv8hwsl8jcv-glibc-locales-2.33 # update the definitions from the Guix repository user@guix-host1:$ guix pull # read any news user@guix-host1:$ guix pull --news user@guix-host1:$ guix pull --news --details # update any packages user@guix-host1:$ guix upgrade
If you have problems with the installer then the extensive manual is the place to start as it's very comprehensive. Some things I've seen:
Congratulations, you now have Guix installed inside an Ubuntu 22.04 LTS system container (lxd). You're ready to start using Guix. But, wow this is quite long enough for a single blog post, so I'm going to stop here! If you're not ready to stop - how about continuing by reading the Guix Reference manual and then come along to the second part.
If you successfully install Guix, or have problems I'd love to hear from you either way!
[1] | I use the core kernel, ubuntu-minimal, X Windows (ubuntu-desktop) and XFCE Desktop from Ubuntu: I want thse to be stable and they don't need to change. My user-space programs like utilities and graphical programs are all from Guix. |
[2] | If your first thought was, "He should have said GNU/Linux there" then beware that this post is likely to have other areas where I haven't obeyed the FSF's orthodoxy, and where I focus on pragmatism over principle. On your blog you can do what you want. |
[3] | See the Reproducible builds site for more and compare Guix capabilities to the SLSA requirements. |