GNU bug report logs - #75810
[PATCH 0/6] Rootless guix-daemon

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Fri, 24 Jan 2025 17:24:02 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


Message #23 received at 75810 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 75810 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 6/6] guix-install.sh: Support the unprivileged daemon where
 possible.
Date: Fri, 24 Jan 2025 18:24:56 +0100
* etc/guix-install.sh (create_account): New function.
(sys_create_build_user): Use it.  When ‘guix-daemon.service’ contains
“User=guix-daemon” only create the ‘guix-daemon’ user and group.
(sys_delete_build_user): Delete the ‘guix-daemon’ user and group.
(can_install_unprivileged_daemon): New function.
(sys_create_store): When installing the unprivileged daemon, change
ownership of /gnu and /var/guix, and create /var/log/guix.
(sys_authorize_build_farms): When the ‘guix-daemon’ account exists,
change ownership of /etc/guix.
(sys_enable_guix_daemon): Do not install ‘gnu-store.mount’ when running
an unprivileged daemon.

Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9
---
 etc/guix-install.sh | 114 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 91 insertions(+), 23 deletions(-)

diff --git a/etc/guix-install.sh b/etc/guix-install.sh
index f07b2741bb..4f08eff847 100755
--- a/etc/guix-install.sh
+++ b/etc/guix-install.sh
@@ -389,6 +389,11 @@ sys_create_store()
     cd "$tmp_path"
     _msg "${INF}Installing /var/guix and /gnu..."
     # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’.
+    #
+    # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing
+    # and unprivileged guix-daemon service; for now, this script may install
+    # from both an old release that does not support unprivileged guix-daemon
+    # and a new release that does, so ‘chown -R’ later if needed.
     tar --extract --strip-components=1 --file "$pkg" -C /
 
     _msg "${INF}Linking the root user's profile"
@@ -414,38 +419,82 @@ sys_delete_store()
     rm -rf ~root/.config/guix
 }
 
+create_account()
+{
+    local user="$1"
+    local group="$2"
+    local supplementary_groups="$3"
+    local comment="$4"
+
+    if id "$user" &>/dev/null; then
+	_msg "${INF}user '$user' is already in the system, reset"
+	usermod -g "$group" -G "$supplementary_groups"	\
+		-d /var/empty -s "$(which nologin)"	\
+		-c "$comment" "$user"
+    else
+	useradd -g "$group" -G "$supplementary_groups"	\
+		-d /var/empty -s "$(which nologin)"	\
+		-c "$comment" --system "$user"
+	_msg "${PAS}user added <$user>"
+    fi
+}
+
+can_install_unprivileged_daemon()
+{ # Return true if we can install guix-daemon running without privileges.
+    [ "$INIT_SYS" = systemd ] && \
+	grep -q "User=guix-daemon" \
+	     ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \
+	&& ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \
+		|| [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ])
+}
+
 sys_create_build_user()
 { # Create the group and user accounts for build users.
 
     _debug "--- [ ${FUNCNAME[0]} ] ---"
 
-    if getent group guixbuild > /dev/null; then
-        _msg "${INF}group guixbuild exists"
-    else
-        groupadd --system guixbuild
-        _msg "${PAS}group <guixbuild> created"
-    fi
-
     if getent group kvm > /dev/null; then
         _msg "${INF}group kvm exists and build users will be added to it"
         local KVMGROUP=,kvm
     fi
 
-    for i in $(seq -w 1 10); do
-        if id "guixbuilder${i}" &>/dev/null; then
-            _msg "${INF}user is already in the system, reset"
-            usermod -g guixbuild -G guixbuild${KVMGROUP}     \
-                    -d /var/empty -s "$(which nologin)" \
-                    -c "Guix build user $i"             \
-                    "guixbuilder${i}";
-        else
-            useradd -g guixbuild -G guixbuild${KVMGROUP}     \
-                    -d /var/empty -s "$(which nologin)" \
-                    -c "Guix build user $i" --system    \
-                    "guixbuilder${i}";
-            _msg "${PAS}user added <guixbuilder${i}>"
-        fi
-    done
+    if [ "$INIT_SYS" = systemd ] && \
+	   grep -q "User=guix-daemon" \
+		~root/.config/guix/current/lib/systemd/system/guix-daemon.service
+    then
+	if getent group guix-daemon > /dev/null; then
+	    _msg "${INF}group guix-daemon exists"
+	else
+	    groupadd --system guix-daemon
+	    _msg "${PAS}group guix-daemon created"
+	fi
+
+	create_account guix-daemon guix-daemon		\
+		       guix-daemon$KVMGROUP		\
+		       "Unprivileged Guix Daemon User"
+
+	# ‘tar xf’ creates root:root files.  Change that.
+	chown -R guix-daemon:guix-daemon	\
+	      /gnu /var/guix
+
+	# The unprivileged cannot create the log directory by itself.
+	mkdir /var/log/guix
+	chown guix-daemon:guix-daemon /var/log/guix
+	chmod 755 /var/log/guix
+    else
+	if getent group guixbuild > /dev/null; then
+            _msg "${INF}group guixbuild exists"
+	else
+            groupadd --system guixbuild
+            _msg "${PAS}group <guixbuild> created"
+	fi
+
+	for i in $(seq -w 1 10); do
+	    create_account "guixbuilder${i}" "guixbuild"	\
+	                   "guixbuild${KVMGROUP}"		\
+			   "Guix build user $i"
+	done
+    fi
 }
 
 sys_delete_build_user()
@@ -460,6 +509,14 @@ sys_delete_build_user()
     if getent group guixbuild &>/dev/null; then
         groupdel -f guixbuild
     fi
+
+    _msg "${INF}remove guix-daemon user"
+    if id guix-daemon &>/dev/null; then
+	userdel -f guix-daemon
+    fi
+    if getent group guix-daemon &>/dev/null; then
+	groupdel -f guix-daemon
+    fi
 }
 
 sys_enable_guix_daemon()
@@ -503,7 +560,14 @@ sys_enable_guix_daemon()
               # Install after guix-daemon.service to avoid a harmless warning.
               # systemd .mount units must be named after the target directory.
               # Here we assume a hard-coded name of /gnu/store.
-              install_unit gnu-store.mount
+	      #
+	      # FIXME: This feature is unavailable when running an
+	      # unprivileged daemon.
+	      if ! grep -q "User=guix-daemon" \
+		   /etc/systemd/system/guix-daemon.service
+	      then
+		  install_unit gnu-store.mount
+	      fi
 
               systemctl daemon-reload &&
                   systemctl start  guix-daemon; } &&
@@ -627,6 +691,10 @@ project's build farms?"; then
 		&& guix archive --authorize < "$key" \
 		&& _msg "${PAS}Authorized public key for $host"
 	done
+	if id guix-daemon &>/dev/null; then
+	    # /etc/guix/acl must be readable by the unprivileged guix-daemon.
+	    chown -R guix-daemon:guix-daemon /etc/guix
+	fi
     else
         _msg "${INF}Skipped authorizing build farm public keys"
     fi
-- 
2.47.1





This bug report was last modified 56 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.