Mastodon

The Guix system, take two

September 02, 2024
Tags:

Let's give a second look at Guix-the-system the main GNU Project distribution I dealt with in a previous post. This post is not specifically limited to the distribution, it is also of interest when using Guix in a foreign distribution, even if some configuration details change.

Substitutes and grafts

As said previously, the daily use of a store-based rolling distribution adds some overhead to the system at both upgrade and installation time. This pain (that remembers me the old times of the source-based Gentoo distribution with its emerge tool) is specifically alleviated by the use of the so-called substitutes servers, which provide pre-built binaries for the base system, as well as alternative/unofficial packages, too.

The fall-back alternative is based on regular build-from-sources on the host system, which could imply long times for both installations and distribution upgrades. The official Guix system comes with a couple of official substitutes (i.e., ci.guix.gnu.org and bordeaux.guix.gnu.org) but others can be added, including possibly any suitable user's server in the LAN.

Another trick in Guix for alleviating the need for long local rebuilds is the use of grafts that are sort of in-place replacements for binary dependencies, expressed at the source level. To explain in brief, if a package A@1 has been replaced by A@2 and they both maintain the same ABI, any reverse dependency B can avoid being rebuilt. This is called a graft in Guix, and greatly simplifies the long chains of forced rebuilds in many cases (for instance, in case of security upgrades). Specifically, the @ in a Guix package is the version separator.

A monorepo for the whole distribution

The Guix source archive is strictly based on git and distributed development by means of a monorepo, which, along with the need to represent the tree of dependencies for any package and its updates at run-time require some operations that are specific of the Guix package management approach:

The pull phase specifically could require ages (hours on my old low-end Asus EEEpc), so it is an operation that should be applied typically in batch mode and quite often in order to minimize execution times. It is not a potentially destructive operation - similar to an apt update with steroids - so it is better to perform it quite often, every few days. At the end of the day, it does not alter the status of the system, so it is safe enough for background execution.

The gc operation works directly on the store to purge obsolete (out of the current status tree of dependencies) entries. If you jump to a past status, the purge would impact bandwidth and CPU loads, of course.

The branch specification has the same role as any sane distributed environment organization of code. It is usable to pull from separate branches of archives, instead of following the default one, latest. This feature can be paired with the Guix time-machine to jump to any past tree of packages in the chronology of the archive sources.

Finally, a channel is simply an alternative archive of sources that is prepared by third-party teams to integrate the official Guix one. For instance, a few independent packages are offered by INRIA and other institutions for the HPC community, as well as an handful of non-free packages hosted on the nonguix repository to solve the well-known users-hostages' dilemma about using closed-source firmwares and a few other proprietary stuff.

One Scheme to Rule Them All

An exciting feature of Guix-the-System is the use of Guile to describe the whole system, including the core, all services, and even users. In perspective, all installed packages could be also fully configured by using functional Guile snippets of code. This is something currently done in Debian only in a limited way, through debconf templates and dpkg selections. In practice, today, one has to use ansible or similar tools to declare configurations in some ad hoc DSL, using tons of plugins and templates, case by case. In a word, it is a mess.

This is, at least for me, the most intriguing feature and open exciting possibilities.

Currently, any developer with a reasonably decent computer can easily use Guix to rebuild and customize Guix itself by starting from a monorepo fork, changing its main configuration and adding/modifying packages in a totally independent and self-consistent way. Something that in traditional distributions is done by a plethora of tools and interfaces, written in multiple generale-purpose or specific languages, and often not wholly documented and held together with the glue.

Once added a layer of general-purpose configurators for common packages the whole distribution generation could become fully autoconsistent and complete for any host or set of boxes. Isn't that challenging?

Guix in foreign distributions

Using Guix as an additional package manager in a foreign distribution has more limitations, of course. First of all, one must deal with systemd as the typical init system. Therefore, the general configuration of the host cannot be expressed in a synthetic way as a Scheme script. That said, it is perfectly possible to use Guix as a development environment for multiple languages ecosystems, thanks to various Guile build modules. Even, it is possible to run Guix-the-system in a container (or a virtual machine), to use the host system just as a basic platform and create Guix-based services and applications on top.

But those will be the topics for other posts...

References