From 474ba557641b184828e21010ba45e01f248b120c Mon Sep 17 00:00:00 2001 From: librelad Date: Sun, 24 May 2026 02:03:11 +0100 Subject: [PATCH] fix(switcher): bulletproof reconcile var/path resolution + diagnostics Previous fix still no-op'd the WebUI-dir chown: in the CLI/switch context the path globals (containers_dir etc.) and the install-user vars can be unset, making webui_dir a relative path the [[ -d ]] check skips, and the chown user empty. Resolve everything with absolute-path fallbacks and read the install user from the live config file when the vars are empty (never empty now), and log what was reconciled (incl. a 'WebUI dir not found' notice) so a switch is diagnosable. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- .../permission/libreportal_folders.sh | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/scripts/function/permission/libreportal_folders.sh b/scripts/function/permission/libreportal_folders.sh index aafe379..9951365 100755 --- a/scripts/function/permission/libreportal_folders.sh +++ b/scripts/function/permission/libreportal_folders.sh @@ -25,39 +25,50 @@ reconcileDockerOwnership() # The control plane is owned by the MANAGER user in BOTH modes. root:root was # never the intended model — it only ever showed up as an artifact of # un-de-sudo'd commands (sudo creating files as root instead of libreportal). + # Robust resolution — these globals aren't always populated in the CLI/switch + # context, which previously made ops silently no-op (relative paths / empty + # user). Fall back to absolute defaults and the live config file; never empty. local owner="${sudo_user_name:-libreportal}" - local appusr="${docker_install_user:-$CFG_DOCKER_INSTALL_USER}" + local ddir="${docker_dir:-/docker}" + local cdir="${containers_dir:-$ddir/containers/}" + local cfgdir="${configs_dir:-$ddir/configs/}" + local logdir="${logs_dir:-$ddir/logs/}" + local scrdir="${script_dir:-$ddir/install}" + local dbpath="$ddir/${db_file:-database.db}" + local appusr="${docker_install_user:-${CFG_DOCKER_INSTALL_USER:-}}" + [[ -z "$appusr" ]] && appusr=$(grep -h '^CFG_DOCKER_INSTALL_USER=' "$cfgdir/general/general_docker_install" 2>/dev/null | head -1 | cut -d= -f2 | awk '{print $1}') + appusr="${appusr:-dockerinstall}" - # Swap ONLY the owner on our own control-plane files; never reset mode bits - # (so nothing that validates its permissions gets surprised). The only two - # bits we *add* (never remove) are structural and on our own dirs, not app - # files: o+x on /docker so the docker user can still traverse to its - # container dirs, and o+r on the DB so the WebUI container can read it. - runSystem chown "$owner:$owner" "$docker_dir" - runSystem chmod o+x "$docker_dir" + [[ -d "$ddir" ]] || return 0 - # LibrePortal-owned control plane (NOT containers/ backups/ ssl/ ssh) — owner - # only, modes preserved. + # Swap ONLY the owner on our own control-plane files; never reset mode bits. + # The only two bits we *add* (never remove) are structural: o+x on /docker so + # the docker user can traverse to its container dirs, and o+r on the DB so the + # WebUI container can read it. + runSystem chown "$owner:$owner" "$ddir" + runSystem chmod o+x "$ddir" local p - for p in "$configs_dir" "$logs_dir" "$script_dir" "$docker_dir/$db_file"; do + for p in "$cfgdir" "$logdir" "$scrdir" "$dbpath"; do [[ -e "$p" ]] && runSystem chown -R "$owner:$owner" "$p" done - [[ -f "$docker_dir/$db_file" ]] && runSystem chmod o+r "$docker_dir/$db_file" + [[ -f "$dbpath" ]] && runSystem chmod o+r "$dbpath" # LibrePortal's OWN WebUI container dir is regenerable, so flip it to the # mode's container owner so the WebUI survives a switch (safe to recurse — - # it's all one UID, no per-app uid to clobber). Third-party app data - # elsewhere under containers/ is left untouched. - # rooted -> the manager (it owns everything under /docker in rooted) + # one UID, no per-app uid to clobber). Third-party app data is left untouched. + # rooted -> the manager (owns everything under /docker in rooted) # rootless -> the docker install user (owns /docker/containers/**) - local webui_dir="${containers_dir}libreportal" + local webui_dir="${cdir}libreportal" if [[ -d "$webui_dir" ]]; then local app_owner="$owner" [[ "$mode" == "rootless" ]] && app_owner="$appusr" runSystem chown -R "$app_owner:$app_owner" "$webui_dir" + isSuccessful "Reconciled WebUI dir ($webui_dir) -> $app_owner" + else + isNotice "reconcileDockerOwnership: WebUI dir '$webui_dir' not found — skipped" fi - isSuccessful "Reconciled LibrePortal control-plane ownership for $mode ($owner)" + isSuccessful "Reconciled ownership for $mode — control plane: $owner, app install user: $appusr" } fixFolderPermissions()