LibrePortal/scripts/cli/commands/webui/cli_webui_commands.sh
librelad 655dbc2bb9 fix(install): restore webui_logins container-group after credential write
The rootless WebUI container reads its bind-mount sources (configs/webui/*)
through the container-owner GROUP since a2376e2 switched those files from
world-readable to 0640 group=container-owner. But the WebUI credential
randomizer rewrites webui_logins via `sed -i` as the non-root manager, which
recreates the file with the manager's own group — dropping the container-owner
group. The installer then started the container immediately, so node hit
EACCES on /app/webui_logins at require-time (parseConfigFile) and exited 1;
nothing listened on the WebUI port. `libreportal webui login reset` had the
same latent bug (rewrite → restart). Under the old world-readable model a
post-sed file stayed o+r so the container could still read it, which is why
this only surfaced on fresh rootless installs after a2376e2.

Fix: make reconcileWebuiDirOwnership the single "ready the WebUI for its
container" pass — it now also restores the configs/webui bind access (new
`webui-bind` ownership action) on top of the container-dir chown. Reorder the
installer so the credential randomizer runs BEFORE the before-start permission
pass, making that pass the last ownership touch before the container starts;
and call reconcileWebuiDirOwnership before the restart in login reset.

Live box recovered via `libreportal-ownership reconcile`; WebUI 200.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-06-21 23:00:47 +01:00

114 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
# WebUI Commands Handler
# Handles all webui subcommands by calling core functions
cliHandleWebuiCommands()
{
local action="$initial_command2"
local config_type="$initial_command3"
local options="$initial_command4"
if [[ -z "$action" ]]; then
cliShowWebuiHelp
fi
case "$action" in
"generate")
if [[ -z "$config_type" ]]; then
isNotice "Generate option required. Use: backup [source] or config [options]"
cliShowWebuiHelp
elif [ "$config_type" = "backup" ]; then
webuiGenerateBackupLocations
webuiGenerateBackupDashboard
webuiGenerateBackupSnapshots "${options:-all}"
webuiGenerateBackupAppStatus
webuiGenerateBackupSchema
webuiGenerateBackupPasswords
elif [ "$config_type" = "system" ]; then
webuiSystemUpdate
elif [ "$config_type" = "config" ]; then
webuiGenerateSystemConfigs
elif [ "$config_type" = "all" ]; then
webuiLibrePortalUpdate
else
isNotice "Invalid generate option: $config_type. Use: backup, system, config, or all"
cliShowWebuiHelp
fi
;;
"service")
installLibrePortalWebUITaskService;
;;
"login")
case "$config_type" in
"show")
sourceScanFiles "libreportal_configs"
if [[ -z "$CFG_WEBUI_USERNAME" || -z "$CFG_WEBUI_PASSWORD" ]]; then
isError "WebUI credentials not found. Run 'libreportal webui login reset' to generate."
return 1
fi
webuiDisplayLogins "show"
;;
"reset"|"recover")
cliWebuiLoginReset
;;
*)
isNotice "Invalid login action: $config_type. Use: show, reset"
cliShowWebuiHelp
;;
esac
;;
"recover")
isNotice "'libreportal webui recover' is deprecated — use 'libreportal webui login reset'."
cliWebuiLoginReset
;;
*)
isNotice "Invalid webui action: $action"
cliShowWebuiHelp
;;
esac
}
cliWebuiLoginReset()
{
local auth_file="$containers_dir/libreportal/frontend/.auth.json"
local webui_logins_file="$configs_dir/webui/webui_logins"
isNotice "Resetting WebUI credentials..."
# Restore placeholders so the scan re-randomizes them
if [ -f "$webui_logins_file" ]; then
runInstallOp sed -i -E 's/^(CFG_WEBUI_USERNAME=).*$/\1RANDOMIZEDUSERNAME1/' "$webui_logins_file"
runInstallOp sed -i -E 's/^(CFG_WEBUI_PASSWORD=).*$/\1RANDOMIZEDPASSWORD1/' "$webui_logins_file"
fi
# Remove auth file to force credential regeneration on next container start
if [ -f "$auth_file" ]; then
rm -f "$auth_file"
isSuccessful "Removed WebUI auth file."
fi
# Re-randomize credentials in webui_logins
scanFileForRandomPasswordKeysUsers "$webui_logins_file"
sourceScanFiles "libreportal_configs"
isSuccessful "WebUI credentials have been reset."
# Regenerate all WebUI config files
isNotice "Regenerating WebUI config files..."
webuiLibrePortalUpdate
# The credential rewrite above ran as the non-root manager, which resets
# webui_logins' group and drops the container-owner group the rootless WebUI
# reads it through. Restore it before restarting, or the container can't read
# its own login file and exits on boot.
reconcileWebuiDirOwnership
# Restart the libreportal container so it picks up the new credentials
isNotice "Restarting LibrePortal container..."
dockerComposeRestart libreportal
isSuccessful "LibrePortal container restarted."
# Display the new credentials
webuiDisplayLogins "reset"
}