Subject: bug#75810: closed (Re: [bug#75810] [PATCH v8 07/16] daemon: Allow running as non-root with unprivileged user namespaces.)

From: [email-masked] (GNU bug Tracking System)
Date: Wed, 26 Mar 2025 17:08:05 +0000

Your bug report

#75810: [PATCH 0/6] Rootless guix-daemon

which was filed against the guix-patches package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
75810: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75810
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: [bug#75810] [PATCH v8 07/16] daemon: Allow running as non-root with unprivileged user namespaces.
From: Ludovic Courtès <[email-masked]>
To: Reepca Russelstein <[email-masked]>
Cc: [email-masked]
Date: Wed, 26 Mar 2025 18:07:13 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Reepca Russelstein <[email-masked]> skribis:

> Looks good to me.

Pushed as a9239a769c5611f12061c9a895e4e218b3445e2f.

  a9239a769c * guix-install.sh: Support the unprivileged daemon where possible.
  107eb8ee8f * etc: systemd services: Run ‘guix-daemon’ as an unprivileged user.
  2f65438eba * tests: Run in a chroot and unprivileged user namespaces.
  f854095b6f * tests: Add missing derivation inputs.
  29164192e9 * linux-container: ‘unprivileged-user-namespace-supported?’ returns #f on non-Linux.
  bdd7b9a45d * daemon: Move comments where they belong.
  0163c732a1 * daemon: Drop Linux ambient capabilities before executing builder.
  a3d6f5ae70 * daemon: Create /var/guix/profiles/per-user unconditionally.
  ae18b3d9e6 * daemon: Allow running as non-root with unprivileged user namespaces.
  40f69b586a * daemon: Remount root directory as read-only.
  93474f9288 * daemon: Remount inputs as read-only.
  550ca89744 * daemon: Bind-mount all the inputs, not just directories.
  5c0b93b244 * daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists.
  7bad04fac0 * daemon: Close the read end of the logging pipe.
  f03e6eff2f * daemon: Use ‘close_range’ where available.

Thanks a *lot*, Reepca.

If you liked this patch series, surely you’ll enjoy this followup:

  https://issues.guix.gnu.org/77288

:-)

Ludo’.

Subject: [PATCH 0/6] Rootless guix-daemon
From: Ludovic Courtès <[email-masked]>
To: [email-masked]
Cc: Ludovic Courtès <[email-masked]>
Date: Fri, 24 Jan 2025 18:23:08 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

From: Ludovic Courtès <[email-masked]>

Hello Guix!

That guix-daemon runs as root is not confidence-inspiring for many.
Initially, the main reason for running it as root was, in the absence
of user namespaces, the fact that builders would be started under one
of the build user accounts, which only root can do.  Now that
unprivileged user namespaces are almost ubiquitous (even on HPC
clusters), this is no longer a good reason.

This patch changes guix-daemon so it can run as an unprivileged
user, using unprivileged user namespaces to still support isolated
builds.  There’s a couple of cases where root is/was still necessary:

  1. To create /var/guix/profiles/per-user/$USER and chown it
     as $USER (see CVE-2019-18192).

  2. To chown /tmp/guix-build-* when using ‘--keep-failed’.

Both can be addressed by giving CAP_CHOWN to guix-daemon, and this is
what this patch series does on distros using systemd.  (For some
reason CAP_CHOWN had to be added to the set of “ambient capabilities”,
which are inherited by child processes; this is why there’s a patch
to drop ambient capabilities in build processes.)

On Guix System (not implemented here), we could address (1) by
creating /var/guix/profiles/per-user/$USER upfront for all the
user accounts.  We could leave (2) unaddressed (so failed build
directories would be owned by guix-daemon:guix-daemon) or we’d
have to pass CAP_CHOWN as well.

There’s another issue: /gnu/store can no longer be remounted
read-only (like we do on Guix System and on systemd with
‘gnu-store.mount’) because then unprivileged guix-daemon would
be unable to remount it read-write (or at least I couldn’t find
a way to do that).  Thus ‘guix-install.sh’ no longer installs
‘gnu-store.mount’ in that case.  It’s a bit sad to lose that
so if anyone can think of a way to achieve it, that’d be great.

I tested all this in a Debian VM¹, along these lines:

  1. GUIX_ALLOW_ME_TO_USE_PRIVATE_COMMIT=yes make update-guix-package
  2. ./pre-inst-env guix pack -C zstd guix --without-tests=guix \
        --localstatedir --profile-name=current-guix
  3. Copy ‘guix-install.sh’ and the tarball to the VM over SSH.
  4. In the VM: GUIX_BINARY_FILE_NAME=pack.tar.zst ./guix-install.sh

The next step (in another patch series) would be Guix System support
with automatic transition (essentially “chown -R
guix-daemon:guix-daemon /gnu/store”).

Thoughts?

Ludo’.

¹ https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-12.9.0-amd64-standard.iso

Ludovic Courtès (6):
  daemon: Allow running as non-root with unprivileged user namespaces.
  DRAFT tests: Run in a chroot and unprivileged user namespaces.
  daemon: Create /var/guix/profiles/per-user unconditionally.
  daemon: Drop Linux ambient capabilities before executing builder.
  etc: systemd services: Run ‘guix-daemon’ as an unprivileged user.
  guix-install.sh: Support the unprivileged daemon where possible.

 build-aux/test-env.in       |  14 +++-
 config-daemon.ac            |   2 +-
 etc/guix-daemon.service.in  |  12 +++-
 etc/guix-install.sh         | 114 ++++++++++++++++++++++++-------
 guix/substitutes.scm        |   4 +-
 nix/libstore/build.cc       | 132 ++++++++++++++++++++++++++++++------
 nix/libstore/local-store.cc |  30 +++++---
 tests/store.scm             |  89 ++++++++++++++----------
 8 files changed, 300 insertions(+), 97 deletions(-)

base-commit: bc6769f1211104dbc9341c064275cd930f5dfa3a
-- 
2.47.1