diff --git a/init.sh b/init.sh index e4dc116..bdb87e1 100755 --- a/init.sh +++ b/init.sh @@ -1109,6 +1109,31 @@ initContainerLayer() isSuccessful "containers/ + backups/ handed to '$duser' (system root traversable)." } +# Give the WebUI container back its read access to the configs/webui bind +# mounts after anything chowns the configs tree. Prefers the root helper (it +# knows the install mode and therefore the right container owner); falls back to +# an inline chown for the first install, where the helper is not baked yet. +# Safe to call when the container user does not exist — it simply does nothing. +restoreWebuiBindAccess() +{ + local helper="/usr/local/lib/libreportal/libreportal-ownership" + if [[ -x "$helper" ]]; then + sudo "$helper" webui-bind 2>/dev/null && return 0 + fi + local wdir="${configs_dir%/}/webui" + [[ -d "$wdir" ]] || return 0 + local dcfg="${configs_dir%/}/general/general_docker_install" + local duser + duser=$(grep -h '^CFG_DOCKER_INSTALL_USER=' "$dcfg" 2>/dev/null | head -1 | cut -d= -f2 | awk '{print $1}') + duser="${duser:-dockerinstall}" + id "$duser" &>/dev/null || return 0 + sudo chmod o+x "${configs_dir%/}" 2>/dev/null + sudo chown "$sudo_user_name:$duser" "$wdir" 2>/dev/null + sudo chmod 0751 "$wdir" 2>/dev/null + sudo find "$wdir" -maxdepth 1 -type f \ + -exec chown "$sudo_user_name:$duser" {} \; -exec chmod 0640 {} \; 2>/dev/null +} + setupConfigsFromRepo() { isNotice "Setting up configuration files from repository..." @@ -1134,6 +1159,13 @@ setupConfigsFromRepo() exit 1 fi sudo chown -R "$sudo_user_name":"$sudo_user_name" "$dst" + # ...but configs/webui/* are BIND-MOUNTED into the WebUI container, which + # reads them through its GROUP (files are 0640, group = container owner). + # The blanket chown above resets that group to the manager, and the portal + # then dies with EACCES on /app/webui_logins the next time it restarts — + # not immediately, so the breakage surfaces long after the deploy that + # caused it. Hand group access straight back. + restoreWebuiBindAccess if [[ ! -f "$dst/general/general_install" ]]; then isError "Configs were copied but $dst/general/general_install is missing." diff --git a/scripts/config/core/variables/config_scan_variables.sh b/scripts/config/core/variables/config_scan_variables.sh index b77181c..a45ac65 100755 --- a/scripts/config/core/variables/config_scan_variables.sh +++ b/scripts/config/core/variables/config_scan_variables.sh @@ -109,4 +109,12 @@ checkConfigFilesMissingVariables() checkLibrePortalConfigFilesMissingVariables; checkApplicationsConfigFilesMissingVariables; + + # Rewriting a live config replaces the file as the MANAGER, which resets the + # group on configs/webui/* — the very files the WebUI container bind-mounts + # and reads through that group (0640). Any release that merely ADDS a key to + # a webui_* config would therefore leave the portal unable to start on its + # next restart. Hand the access back as part of the reconcile itself. + declare -f reconcileWebuiDirOwnership >/dev/null 2>&1 && reconcileWebuiDirOwnership >/dev/null 2>&1 + return 0 }