Convert the remaining ad-hoc 'sudo' calls across the data plane to the run_privileged helpers so every file op lands as the correct owner with no blanket root: - DB/configs (manager-owned): db_list_all_apps, delete_db_file, install_sqlite, cli_webui_commands -> runInstallOp - containers (dockerinstall-owned): scan_container_socket, delete_data, webui_task_files, webui_app_log, webui_config_patch, application_missing_variables, uninstall_app -> runFileOp/runFileWrite - genuine root: passwd, tailscale, ufw-docker, sysctl grep, systemd unit read, authorized_keys read, nobody chown -> runSystem - interactive editors and 'id -u': drop sudo entirely (run as caller) - owncloud/adguard container-UID config edits -> runSystem (funnel; docker-exec rework deferred) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
91 lines
3.6 KiB
Bash
Executable File
91 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# LibrePortal Task Processor Systemd Service Setup
|
|
# Replaces crontabSetupTaskProcessor with systemd service.
|
|
#
|
|
# Idempotent: computes the desired unit for the CURRENT docker mode and only
|
|
# rewrites + daemon-reloads + restarts when it actually differs from what's on
|
|
# disk. So routine re-runs are no-ops (no needless restart that would kill an
|
|
# in-flight task), while a rooted<->rootless switch — which changes the env
|
|
# block — triggers exactly one rewrite + restart so the processor re-reads the
|
|
# new mode. Safe to call from install AND from the docker-type switcher.
|
|
installLibrePortalWebUITaskService()
|
|
{
|
|
[[ "$CFG_REQUIREMENT_WEBUI_SERVICE" == "true" ]] || return 0
|
|
|
|
local service_file="/etc/systemd/system/libreportal.service"
|
|
local task_processor_script="$install_scripts_dir/crontab/task/crontab_task_processor.sh"
|
|
local task_dir="$containers_dir/libreportal/frontend/data/tasks"
|
|
|
|
# Point the processor at the task dir (idempotent).
|
|
if [ -f "$task_processor_script" ]; then
|
|
sed -i "s|TASK_DIR=\".*\"|TASK_DIR=\"$task_dir\"|g" "$task_processor_script"
|
|
chmod +x "$task_processor_script"
|
|
else
|
|
isNotice "Task processor script not found"
|
|
fi
|
|
|
|
# Rootless docker exposes the daemon at /run/user/<uid>/docker.sock and depends
|
|
# on XDG_RUNTIME_DIR being set. Systemd units don't inherit user bashrc, so
|
|
# without these Environment= lines the processor would fall back to
|
|
# /var/run/docker.sock (which rootless does not create). The rootless daemon
|
|
# runs as the DOCKER INSTALL USER, so its socket lives in THAT user's runtime
|
|
# dir (matches dockerCommandRunInstallUser). Rooted gets no extras — the
|
|
# default /var/run path is already correct.
|
|
local service_env_block=""
|
|
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
|
|
local docker_install_uid
|
|
docker_install_uid="$(id -u "$CFG_DOCKER_INSTALL_USER")"
|
|
service_env_block="Environment=DOCKER_HOST=unix:///run/user/${docker_install_uid}/docker.sock
|
|
Environment=XDG_RUNTIME_DIR=/run/user/${docker_install_uid}"
|
|
fi
|
|
|
|
local desired
|
|
desired="$(cat <<EOF
|
|
[Unit]
|
|
Description=LibrePortal Task Processor
|
|
After=network.target
|
|
Wants=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=$sudo_user_name
|
|
Group=$sudo_user_name
|
|
WorkingDirectory=$install_scripts_dir
|
|
ExecStart=$task_processor_script start_script
|
|
Restart=always
|
|
RestartSec=5
|
|
SyslogIdentifier=libreportal
|
|
${service_env_block}
|
|
|
|
# Security
|
|
PrivateTmp=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
)"
|
|
|
|
local current=""
|
|
[[ -f "$service_file" ]] && current="$(runSystem cat "$service_file" 2>/dev/null)"
|
|
|
|
if [[ "$desired" != "$current" ]]; then
|
|
printf '%s\n' "$desired" | runSystem tee "$service_file" > /dev/null
|
|
runSystem systemctl daemon-reload
|
|
runSystem systemctl enable libreportal.service >/dev/null 2>&1
|
|
runSystem systemctl restart libreportal.service
|
|
isSuccessful "LibrePortal task processor service installed/updated ($CFG_DOCKER_INSTALL_TYPE)."
|
|
else
|
|
# Unit already correct — ensure it's enabled + running, without a restart.
|
|
runSystem systemctl enable libreportal.service >/dev/null 2>&1
|
|
runSystem systemctl is-active --quiet libreportal.service || runSystem systemctl start libreportal.service
|
|
isSuccessful "LibrePortal task processor service already up to date."
|
|
fi
|
|
|
|
# Drop the legacy crontab entry if present (superseded by the service).
|
|
if sudo -u "$sudo_user_name" crontab -l 2>/dev/null | grep -q "task_processor.sh"; then
|
|
sudo -u "$sudo_user_name" crontab -l 2>/dev/null | grep -v "task_processor.sh" | sudo -u "$sudo_user_name" crontab -
|
|
isNotice "Removed task processor from crontab"
|
|
fi
|
|
}
|