2.2.1 Build Environment Setup
In a standard multi-user setup, Guix and its daemon—the
guix-daemon program—are installed by the system
administrator. Unprivileged users may use Guix tools to build packages
or otherwise access the store, and the daemon will do it on their
behalf, ensuring that the store is kept in a consistent state, and
allowing built packages to be shared among users.
There are currently two ways to set up and run the build daemon:
- running
guix-daemonas “root”, letting it run build processes as unprivileged users taken from a pool of build users—this is the historical approach; - running
guix-daemonas a separate unprivileged user, relying on Linux’s unprivileged user namespace functionality to set up isolated environments—this is the option chosen when installing Guix on a systemd-based distribution with the installation script (see Binary Installation).
The sections below describe each of these two configurations in more detail and summarize the kind of build isolation they provide.
- Daemon Running as Root
- Daemon Running Without Privileges
- Migrating to the Unprivileged Daemon
- The Isolated Build Environment
Daemon Running as Root
When guix-daemon runs as root, you may not want package
build processes themselves to run as root too, for obvious
security reasons. To avoid that, a special pool of build users
should be created for use by build processes started by the daemon.
Having several such users allows the daemon to launch
distinct build processes under separate UIDs, which guarantees that they
do not interfere with each other—an essential feature since builds are
regarded as pure functions (see Introduction).
On a GNU/Linux system, a build user pool may be created like this (using
Bash syntax and the shadow commands):
# 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
The number of build users determines how many build jobs may run in
parallel, as specified by the --max-jobs option
(see --max-jobs). To use
guix system vm and related commands, you may need to add the
build users to the kvm group so they can access /dev/kvm,
using -G guixbuild,kvm instead of -G guixbuild
(see Invoking guix system).
The guix-daemon program may then be run as root with the
following command5:
# guix-daemon --build-users-group=guixbuild
In this setup, /gnu/store is owned by root.
Daemon Running Without Privileges
The second and preferred option is to run guix-daemon
as an unprivileged user. It has the advantage of reducing the
harm that can be done should a build process manage to exploit a
vulnerability in the daemon. This option requires the use of Linux’s
unprivileged user namespace mechanism; today it is available and enabled
by most GNU/Linux distributions but can still be disabled. The
installation script automatically determines whether this option is
available on your system (see Binary Installation).
When using this option, you only need to create one user account, and
guix-daemon will run with the authority of that account:
# groupadd --system guix-daemon
# useradd -g guix-daemon -G guix-daemon \
-d /var/empty -s $(which nologin) \
-c "Guix daemon privilege separation user" \
--system guix-daemon
Warning: If the
nologinbinary is not found bywhich nologin, you may need to specify its path manually. This will usually be /sbin/nologin or /usr/sbin/nologin.
In this configuration, /gnu/store is owned by the
guix-daemon user.
Migrating to the Unprivileged Daemon
To switch an existing installation to the unprivileged execution mode, a
number of steps must be taken: creating a new dedicated
guix-daemon user account, changing ownership of the relevant
files to guix-daemon, and ensuring that the guix-daemon
program runs as guix-daemon.
On Guix System, these steps are carried out automatically when you set
the privileged? field of the guix-configuration record to
#f and reconfigure (see guix-configuration).
However, on a foreign distribution, the process is manual. The following paragraphs describe what you need to do.
Warning: Follow the instructions below only after making sure you have a recent version of
guix-daemonwith support for unprivileged execution.
File ownership can be changed, after stopping the daemon, by running the
following commands as root (the chown can take a while if
there are many files in /gnu/store):
groupadd --system guix-daemon
useradd -g guix-daemon -G guix-daemon,kvm \
-d /var/empty -s $(which nologin) \
-c "Guix daemon privilege separation user" \
--system guix-daemon
# Make the store writable, in case the systemd 'gnu-store.mount'
# unit made it read-only.
mount -o remount,rw /gnu/store
chown -R guix-daemon:guix-daemon \
/gnu \
/var/guix/{gc.lock,daemon-socket,db,discover} \
/var/guix/{gcroots,offload,substitute,temproots} \
/var/log/guix \
/etc/guix
If your system uses the systemd service manager, running the daemon as
guix-daemon will be a matter of copying the relevant
configuration files—make sure to review any changes you might have
made in your own .service files before overwriting them:
cp /var/guix/profiles/per-user/root/current-guix/lib/systemd/system/*.service \ /etc/systemd/system systemctl daemon-reload systemctl start guix-daemon
If your system has AppArmor enabled, see AppArmor Support.
Warning: The commands above assume that
guix pullwas run for the root user. You can check whether this is the case by running this command:grep User=guix-daemon \ /var/guix/profiles/per-user/root/current-guix/lib/systemd/system/guix-daemon.serviceIf that command does not show the
User=guix-daemonline, then runguix pullas the root user.
The Isolated Build Environment
In both cases, privileged and unprivileged, the daemon starts build processes without privileges in an isolated or hermetic build environment—a “chroot”. On GNU/Linux, by default, the build environment contains nothing but:
- a minimal
/devdirectory, created mostly independently from the host/dev6; - the
/procdirectory; it only shows the processes of the container since a separate PID name space is used; - /etc/passwd with an entry for the current user and an entry for user nobody;
- /etc/group with an entry for the user’s group;
- /etc/hosts with an entry that maps
localhostto127.0.0.1; - a writable /tmp directory.
The chroot does not contain a /home directory, and the HOME
environment variable is set to the non-existent
/homeless-shelter. This helps to highlight inappropriate uses of
HOME in the build scripts of packages.
All this is usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed—typically over the date, kernel, or CPU—you can resort to a virtual build machine (see virtual build machines).
You can influence the directory where the daemon stores build trees
via the TMPDIR environment variable. However, the build tree
within the chroot is always called /tmp/guix-build-name.drv-0,
where name is the derivation name—e.g., coreutils-8.24.
This way, the value of TMPDIR does not leak inside build
environments, which avoids discrepancies in cases where build processes
capture the name of their build tree.
The daemon also honors the http_proxy and https_proxy
environment variables for HTTP and HTTPS downloads it performs, be it
for fixed-output derivations (see Derivations) or for substitutes
(see Substitutes).
Footnotes
(5)
If your machine uses the systemd init system,
copying the prefix/lib/systemd/system/guix-daemon.service
file to /etc/systemd/system will ensure that
guix-daemon is automatically started. Similarly, if your
machine uses the Upstart init system, copy the
prefix/lib/upstart/system/guix-daemon.conf
file to /etc/init.
(6)
“Mostly”, because while the set of files
that appear in the chroot’s /dev is fixed, most of these files
can only be created if the host has them.