LibrePortal/scripts/docker/command/docker_run_install.sh
librelad 3a0bcaccb6 fix(rootless): run install-user commands from HOME, not the caller cwd
dockerCommandRunInstallUser sudo's to the unprivileged docker install user but
inherited the caller's cwd. At install time the caller is root in /root, which
that user can't enter, so cwd-sensitive tools failed — e.g. 'find: Failed to
change directory: /root' / 'Failed to restore initial working directory'
during the app scan (the scan still worked via the absolute start path, but
the errors are noise and could bite other commands). Add env --chdir to the
install user's HOME for both the argv and shell exec paths so every runFileOp
runs from a directory the user can access.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-24 13:50:20 +01:00

66 lines
2.7 KiB
Bash
Executable File

#!/bin/bash
# Run a command as the unprivileged rootless Docker install user.
#
# This used to ssh to <user>@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/<uid> 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=""
local argv_mode=""
while true; do
case "$1" in
--silent) silent_flag="1"; shift ;;
--argv) argv_mode="1"; shift ;;
*) break ;;
esac
done
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
# 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"
)
# Run from the install user's HOME, not the caller's cwd. At install time the
# caller is root in /root, which the unprivileged user can't enter, so
# cwd-sensitive tools error (e.g. find: "Failed to change directory: /root").
local run_cwd="/home/$CFG_DOCKER_INSTALL_USER"
# --argv: exec the remaining args verbatim (no shell re-parse) so regex/
# quotes/backslashes in arguments (e.g. sed scripts) survive intact. Default:
# treat $1 as a shell snippet via bash -c (needed for pipes/redirects/
# systemctl --user/etc.).
if [ -n "$argv_mode" ]; then
if [ -n "$silent_flag" ]; then
sudo -u "$CFG_DOCKER_INSTALL_USER" env --chdir="$run_cwd" "${run_env[@]}" "$@" >/dev/null 2>&1
else
sudo -u "$CFG_DOCKER_INSTALL_USER" env --chdir="$run_cwd" "${run_env[@]}" "$@"
fi
else
local remote_command="$1"
if [ -n "$silent_flag" ]; then
sudo -u "$CFG_DOCKER_INSTALL_USER" env --chdir="$run_cwd" "${run_env[@]}" bash -c "$remote_command" >/dev/null 2>&1
else
sudo -u "$CFG_DOCKER_INSTALL_USER" env --chdir="$run_cwd" "${run_env[@]}" bash -c "$remote_command"
fi
fi
}