From 49c1a23221d5fcb4bfcefa3408360cee60d303d8 Mon Sep 17 00:00:00 2001 From: librelad Date: Sat, 23 May 2026 21:42:29 +0100 Subject: [PATCH] fix(rootless): run install-user commands via sudo -u, not SSH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dockerCommandRunInstallUser ssh'd to @localhost, but nothing set up an SSH server/keys/authorized_keys, so every rootless setup command (daemon install, systemctl --user) silently no-op'd. Replace with 'sudo -u env …' that sets XDG_RUNTIME_DIR / DBUS_SESSION_BUS_ADDRESS / DOCKER_HOST / PATH explicitly; linger keeps the user systemd + /run/user/ alive so systemctl --user works. No SSH server, no keys, less attack surface, and sudo -u to an unprivileged user is not a root escalation. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- scripts/docker/command/docker_run_install.sh | 55 ++++++++++---------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/scripts/docker/command/docker_run_install.sh b/scripts/docker/command/docker_run_install.sh index c5c2fa0..fb8a69a 100755 --- a/scripts/docker/command/docker_run_install.sh +++ b/scripts/docker/command/docker_run_install.sh @@ -1,6 +1,17 @@ #!/bin/bash -dockerCommandRunInstallUser() +# Run a command as the unprivileged rootless Docker install user. +# +# This used to ssh to @localhost to get a fully-initialised user session +# (so `systemctl --user` and the rootless dockerd would work). That needs an SSH +# server, a generated key and authorized_keys — none of which the install set +# up, so the whole rootless path silently no-op'd. Instead run via `sudo -u` +# with the session env set explicitly: `loginctl enable-linger` (done during +# rootless setup) keeps the user's `systemd --user` and /run/user/ alive, +# so `systemctl --user` works, and DOCKER_HOST points at the rootless socket. +# `sudo -u` to an unprivileged user is not a root escalation, and there's no SSH +# attack surface. +dockerCommandRunInstallUser() { local silent_flag="" if [ "$1" == "--silent" ]; then @@ -9,35 +20,25 @@ dockerCommandRunInstallUser() fi local remote_command="$1" - # Get the value of PasswordAuthentication from sshd_config - local result=$(sudo sed -i '/#PasswordAuthentication/d' $sshd_config) - local passwordAuth=$(grep -i "^PasswordAuthentication" $sshd_config | awk '{print $2}') - - # Keys - local private_path="${ssh_dir}private/" - local install_user_key="${CFG_INSTALL_NAME}_sshkey_${CFG_DOCKER_INSTALL_USER}" - - # Run the SSH command using the existing SSH variables - local output - if [ "$passwordAuth" == "no" ]; then - if [ -z "$silent_flag" ]; then - ssh -i "${private_path}${install_user_key}" -o StrictHostKeyChecking=no "$CFG_DOCKER_INSTALL_USER@localhost" "$remote_command" - else - ssh -i "${private_path}${install_user_key}" -o StrictHostKeyChecking=no "$CFG_DOCKER_INSTALL_USER@localhost" "$remote_command" > /dev/null 2>&1 - fi - else - if [ -z "$silent_flag" ]; then - sshpass -p "$CFG_DOCKER_INSTALL_PASS" ssh -o StrictHostKeyChecking=no "$CFG_DOCKER_INSTALL_USER@localhost" "$remote_command" - else - sshpass -p "$CFG_DOCKER_INSTALL_PASS" ssh -o StrictHostKeyChecking=no "$CFG_DOCKER_INSTALL_USER@localhost" "$remote_command" > /dev/null 2>&1 - fi + local uid + uid=$(id -u "$CFG_DOCKER_INSTALL_USER" 2>/dev/null) + if [ -z "$uid" ]; then + isError "Cannot run as '$CFG_DOCKER_INSTALL_USER' — user does not exist." + return 1 fi - local exit_code=$? + # rootless docker installs its binaries to the user's ~/bin, so include it. + local run_env=( + "HOME=/home/$CFG_DOCKER_INSTALL_USER" + "XDG_RUNTIME_DIR=/run/user/$uid" + "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus" + "DOCKER_HOST=unix:///run/user/$uid/docker.sock" + "PATH=/home/$CFG_DOCKER_INSTALL_USER/bin:/usr/bin:/bin:/usr/local/bin" + ) - if [ $exit_code -eq 0 ]; then - : + if [ -n "$silent_flag" ]; then + sudo -u "$CFG_DOCKER_INSTALL_USER" env "${run_env[@]}" bash -c "$remote_command" >/dev/null 2>&1 else - : + sudo -u "$CFG_DOCKER_INSTALL_USER" env "${run_env[@]}" bash -c "$remote_command" fi }