fix(install): keep the WebUI's bind-mount access after a config chown
The portal was found crash-looping with EACCES on /app/webui_logins.
configs/webui/* are bind-mounted into the container, which reads them
through its GROUP (files 0640, group = container owner). Two paths reset
that group to the manager and never gave it back:
* init.sh setupConfigsFromRepo — `chown -R manager:manager` over the
whole configs tree on every install/redeploy (the documented local-
mode deploy), and
* the runtime config reconcile — rewriting a live config replaces the
file as the manager, so ANY release that merely adds a key to a
webui_* config would break the portal.
Neither breaks anything immediately: the running container holds its
open files, so the failure only appears at the next restart, long after
the change that caused it. That is exactly how it surfaced here — a
deploy in the evening, a dead WebUI later.
init.sh gains restoreWebuiBindAccess (prefers the root ownership helper,
inline chown fallback for the first install, no-op when the container
user does not exist yet) called right after the chown; the reconcile
calls the existing reconcileWebuiDirOwnership when it is in scope.
Verified by reproducing the break (chown -R manager over configs), then
running the fixed deploy and force-recreating the container: group is
restored to the container owner and the portal serves on 3179.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
23cef6f427
commit
3325c53855
32
init.sh
32
init.sh
@ -1109,6 +1109,31 @@ initContainerLayer()
|
|||||||
isSuccessful "containers/ + backups/ handed to '$duser' (system root traversable)."
|
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()
|
setupConfigsFromRepo()
|
||||||
{
|
{
|
||||||
isNotice "Setting up configuration files from repository..."
|
isNotice "Setting up configuration files from repository..."
|
||||||
@ -1134,6 +1159,13 @@ setupConfigsFromRepo()
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sudo chown -R "$sudo_user_name":"$sudo_user_name" "$dst"
|
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
|
if [[ ! -f "$dst/general/general_install" ]]; then
|
||||||
isError "Configs were copied but $dst/general/general_install is missing."
|
isError "Configs were copied but $dst/general/general_install is missing."
|
||||||
|
|||||||
@ -109,4 +109,12 @@ checkConfigFilesMissingVariables()
|
|||||||
|
|
||||||
checkLibrePortalConfigFilesMissingVariables;
|
checkLibrePortalConfigFilesMissingVariables;
|
||||||
checkApplicationsConfigFilesMissingVariables;
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user