fix(rootless): task processor must load the de-sudo helpers itself

systemd launches the processor standalone, so it never sourced the LibrePortal
function library — runFileOp/runFileWrite were 'command not found' at runtime,
so it couldn't write its log, create its lock (flock died on a bad fd), or
update task status. Every task stayed queued and looped forever, and the setup
'finalize' never ran.

Source the privilege helpers (run_privileged.sh, docker_run_install.sh,
check_install_type.sh) + read the docker-type config at startup so runFileOp
knows rooted vs rootless. Also create the lock and per-task log via runFileOp
(world-writable) so the manager-user processor can open/append them in the
docker-install-owned task dir.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-24 14:42:16 +01:00
parent 9ecb7e5f35
commit d3f073a107

View File

@ -25,6 +25,27 @@ script_task_processor_flag="$1"
# Source guard — DO NOT remove. mainLoop is an infinite loop.
[[ "$script_task_processor_flag" != "start_script" ]] && return 0 2>/dev/null
# --- Load the privilege helpers + docker-type config ------------------------
# systemd launches this script standalone, so the de-sudo helpers
# (runFileOp/runFileWrite) and the config they key off (rooted vs rootless) are
# NOT otherwise in scope. Without them every privileged write into the
# docker-install-owned task dir fails ("command not found") and tasks loop
# forever. Load them here — these files are pure function/var defs, safe to
# source, no side effects.
LP_SCRIPTS="${install_scripts_dir:-/docker/install/scripts/}"
LP_DOCKER_CFG="/docker/configs/general/general_docker_install"
[[ -f "$LP_DOCKER_CFG" ]] && \
eval "$(grep -E '^CFG_DOCKER_INSTALL_(TYPE|USER)=' "$LP_DOCKER_CFG" | sed 's/[[:space:]]*#.*//')"
: "${sudo_user_name:=libreportal}"
: "${containers_dir:=/docker/containers/}"
: "${docker_dir:=/docker}"
for _lp_f in docker/command/run_privileged.sh \
docker/command/docker_run_install.sh \
checks/requirements/check_install_type.sh; do
[[ -f "${LP_SCRIPTS}${_lp_f}" ]] && source "${LP_SCRIPTS}${_lp_f}"
done
command -v resolveDockerInstallUser >/dev/null 2>&1 && resolveDockerInstallUser
# ============================================================================
# PATHS & CONSTANTS
# ============================================================================
@ -116,6 +137,12 @@ setupTaskDir() {
fi
runFileOp chmod 666 "$FIFO" 2>/dev/null
runFileOp chmod 755 "$TASK_DIR" 2>/dev/null
# The processor (manager user) can't create files in the docker-install-owned
# task dir, so pre-create the lock AS the dir owner, world-writable, so the
# `exec 200>"$LOCK_FILE"` in acquireSingletonLock (run as the manager) can open
# it. Create-if-absent to keep a stable inode for flock across restarts.
[[ -e "$LOCK_FILE" ]] || runFileOp install -m 666 /dev/null "$LOCK_FILE" 2>/dev/null
runFileOp chmod 666 "$LOCK_FILE" 2>/dev/null
if [[ -n "$docker_install_user" ]]; then
runFileOp chown -R "$docker_install_user":"$docker_install_user" "$TASK_DIR" 2>/dev/null
fi
@ -218,14 +245,14 @@ runTask() {
# Previously this used `sudo truncate` + `sudo chmod 644` which left the file
# root-owned and unwritable to the daemon, so the redirection failed and the
# task immediately exited with rc=1.
local daemonUser; daemonUser=$(id -un)
if [[ -f "$logFile" ]]; then
runFileOp chown "$daemonUser":"$daemonUser" "$logFile" 2>/dev/null
runFileOp chmod 664 "$logFile" 2>/dev/null
: > "$logFile" 2>/dev/null || runFileOp truncate -s 0 "$logFile" 2>/dev/null
else
: > "$logFile" 2>/dev/null || runFileOp install -o "$daemonUser" -g "$daemonUser" -m 664 /dev/null "$logFile"
fi
# TASK_DIR is owned by the docker install user, so the manager-user processor
# can't create the log there directly. Create/truncate it AS the dir owner via
# runFileOp and leave it world-writable for the run so the eval's
# `>>"$logFile"` append (which runs as the manager, NOT under sudo) succeeds.
# Re-owned to the dir owner when the task finishes.
runFileOp install -m 666 /dev/null "$logFile" 2>/dev/null \
|| runFileOp truncate -s 0 "$logFile" 2>/dev/null
runFileOp chmod 666 "$logFile" 2>/dev/null
export LIBREPORTAL_NONINTERACTIVE=1