refactor(storage): route elevation tests and the WebUI tree through paths.sh
Two mechanical sweeps, no behaviour change on a single-root install. The 14 `[[ "$p" == "$containers_dir"* ]]` prefix tests that decide manager-vs-container-user elevation become pathIsContainerData, so a file on a second storage root is no longer misclassified as manager-owned — which would have written it with the wrong owner and failed later, far from the cause. The 65 references to the WebUI's own tree become webuiDir(), which is pinned to the primary root by design. Two traps found while doing it: run_privileged.sh is sourced directly by init.sh without paths.sh, so it needs a fallback. Defining one named pathIsContainerData was wrong: generate_function_manifest.sh indexes top-level definitions, and the resulting autoload stub would have shadowed the real multi-root implementation with the primary-only fallback — silently classifying every file on a second disk as manager-owned, which is exactly the bug this sweep exists to prevent. Renamed to _runCfgIsContainerPath, which delegates when the real one is loaded. setup_lock.sh built its path in a top-level assignment, so it was evaluated at source time and needed the file flagged eager. Made it a function instead: the path resolves on call, and the file drops off LP_EAGER_FILES entirely. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
db04f8f000
commit
2d24a764a8
@ -5,7 +5,7 @@
|
||||
# mount set takes effect.
|
||||
crowdsecToggleLibrePortalLogMounts() {
|
||||
local mode="$1"
|
||||
local compose="${containers_dir}libreportal/docker-compose.yml"
|
||||
local compose="$(webuiDir)/docker-compose.yml"
|
||||
[[ -f "$compose" ]] || return 0
|
||||
|
||||
case "$mode" in
|
||||
@ -26,7 +26,7 @@ crowdsecToggleLibrePortalLogMounts() {
|
||||
|
||||
if runFileOp docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^libreportal-service$'; then
|
||||
isNotice "Recreating libreportal so log mount toggle takes effect..."
|
||||
( cd "${containers_dir}libreportal" && runAsManager docker compose up -d >/dev/null 2>&1 ) || true
|
||||
( cd "$(webuiDir)" && runAsManager docker compose up -d >/dev/null 2>&1 ) || true
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
appDashyUpdateConf()
|
||||
{
|
||||
local conf_file="${containers_dir}dashy/etc/conf.yml"
|
||||
local services_json="${containers_dir}libreportal/frontend/data/apps/generated/apps-services.json"
|
||||
local icons_src_dir="${containers_dir}libreportal/frontend/icons/apps"
|
||||
local services_json="$(webuiDir)/frontend/data/apps/generated/apps-services.json"
|
||||
local icons_src_dir="$(webuiDir)/frontend/icons/apps"
|
||||
|
||||
# Don't check the apps DB here — appUpdateSpecifics calls us at
|
||||
# install step 6, BEFORE databaseInstallApp (step 8) writes the
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
# gluetun adds/removes providers and protocols. Falls back silently to the
|
||||
# previous snapshot (or the bundled default) on network failure.
|
||||
appWebuiRefresh_gluetun() {
|
||||
local output_file="${containers_dir}libreportal/frontend/data/apps/generated/gluetun-providers.json"
|
||||
local output_file="$(webuiDir)/frontend/data/apps/generated/gluetun-providers.json"
|
||||
local upstream="https://raw.githubusercontent.com/qdm12/gluetun/master/internal/storage/servers.json"
|
||||
local tmp="$(mktemp)"
|
||||
local raw="${output_file}.raw.$$"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
# override flag. Skips itself, Traefik, LibrePortal, fail2ban.
|
||||
gluetunRouteExistingAppsPrompt()
|
||||
{
|
||||
local categories_file="${containers_dir}libreportal/frontend/data/apps/gluetun-eligible-categories.json"
|
||||
local categories_file="$(webuiDir)/frontend/data/apps/gluetun-eligible-categories.json"
|
||||
local override="${CFG_REQUIREMENT_GLUETUN_FOR_ALL:-false}"
|
||||
|
||||
if ! command -v sqlite3 >/dev/null 2>&1 || [[ ! -f "$docker_dir/$db_file" ]]; then
|
||||
|
||||
@ -25,7 +25,7 @@ libreportal_catalog_install_post_setup()
|
||||
# Bundle the App Center's category icons so the site's sidebar matches the
|
||||
# WebUI (same per-category glyphs). Copied from the live frontend so they
|
||||
# stay in step; best-effort (the site falls back to misc.svg if absent).
|
||||
local cat_src="$containers_dir/libreportal/frontend/core/icons/categories"
|
||||
local cat_src="$(webuiDir)/frontend/core/icons/categories"
|
||||
if [[ -d "$cat_src" ]]; then
|
||||
runFileOp mkdir -p "$dest/categories" || true
|
||||
runFileOp cp -f "$cat_src"/*.svg "$dest/categories/" 2>/dev/null || true
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
cliAppToolList()
|
||||
{
|
||||
local filter_app="$1"
|
||||
local manifest="$containers_dir/libreportal/frontend/data/apps/generated/apps-tools.json"
|
||||
local manifest="$(webuiDir)/frontend/data/apps/generated/apps-tools.json"
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
isError "apps-tools.json not found at $manifest. Run the WebUI updater to generate it."
|
||||
|
||||
@ -194,7 +194,7 @@ updaterSetAnchorRef()
|
||||
# — i.e. the roll-back target. Read from history.json's most recent update/ok.
|
||||
updaterLastUpdateFrom()
|
||||
{
|
||||
local app="$1" hist="$containers_dir/libreportal/frontend/data/updater/generated/history.json"
|
||||
local app="$1" hist="$(webuiDir)/frontend/data/updater/generated/history.json"
|
||||
[ -f "$hist" ] && command -v jq >/dev/null 2>&1 || return 0
|
||||
jq -r --arg a "$app" 'first(.entries[]? | select(.app==$a and .action=="update" and .result=="ok") | .from) // ""' "$hist" 2>/dev/null
|
||||
}
|
||||
@ -336,7 +336,7 @@ updaterRecordHistory()
|
||||
{
|
||||
local app="$1" action="$2" from="$3" to="$4" result="$5"
|
||||
local artifact_id="${6:-}" serial="${7:-}" undo_id="${8:-}" trigger="${9:-manual}"
|
||||
local f="$containers_dir/libreportal/frontend/data/updater/generated/history.json"
|
||||
local f="$(webuiDir)/frontend/data/updater/generated/history.json"
|
||||
local ts; ts="$(date -Iseconds 2>/dev/null || date)"
|
||||
[ -f "$f" ] || printf '{ "entries": [] }\n' | runFileWrite "$f"
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ cliHandleWebuiCommands()
|
||||
|
||||
cliWebuiLoginReset()
|
||||
{
|
||||
local auth_file="$containers_dir/libreportal/frontend/.auth.json"
|
||||
local auth_file="$(webuiDir)/frontend/.auth.json"
|
||||
local webui_logins_file="$configs_dir/webui/webui_logins"
|
||||
|
||||
isNotice "Resetting WebUI credentials..."
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
# crontab_task_processor.sh and webui_task_create.sh use; if those move, both
|
||||
# this file and they have to update together.
|
||||
_taskDir() {
|
||||
echo "${containers_dir}libreportal/frontend/data/tasks"
|
||||
echo "$(webuiDir)/frontend/data/tasks"
|
||||
}
|
||||
|
||||
_genTaskId() {
|
||||
|
||||
@ -142,7 +142,7 @@ reconcileConfigFile()
|
||||
if [[ -s "$tmp" ]] && grep -q '^CFG_' "$tmp" && ! runInstallOp cmp -s "$tmp" "$live"; then
|
||||
local bak_file="${live%/*}/.${live##*/}.bak"
|
||||
runCfgOp cp -a "$live" "$bak_file"
|
||||
{ [[ -n "$containers_dir" && "$live" == "$containers_dir"* ]] && runFileWrite "$live" < "$tmp" || runInstallOp cp "$tmp" "$live"; }
|
||||
{ pathIsContainerData "$live" && runFileWrite "$live" < "$tmp" || runInstallOp cp "$tmp" "$live"; }
|
||||
# A hidden .<file>.bak sibling is still written above for safety; the
|
||||
# per-file result is intentionally silent — the intro notice and the
|
||||
# per-section "...completed." lines are the only reconcile output.
|
||||
|
||||
@ -51,6 +51,6 @@ tagsManagerUpdateUniversalTag()
|
||||
# manager-owned configs/ + install templates use runInstallOp. The read
|
||||
# (awk above) needs no escalation — config/compose files are world-readable.
|
||||
local op="runInstallOp"
|
||||
[[ "$file_path" == "$containers_dir"* || "$file_path" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$file_path" && op="runFileOp"
|
||||
$op sed -i "/#LIBREPORTAL|${tag_name}|/s|${esc_placeholder}|${esc_new}|g" "$file_path"
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ dockerUninstallApp()
|
||||
# scan happened to run. Surgical delete rather than a rescan: a full
|
||||
# updater scan re-runs CVE checks against every image and has no place
|
||||
# inside an uninstall.
|
||||
local _upd_gen="${containers_dir}libreportal/frontend/data/updater/generated"
|
||||
local _upd_gen="$(webuiDir)/frontend/data/updater/generated"
|
||||
local _upd_f
|
||||
for _upd_f in updates.json cves.json; do
|
||||
if [[ -f "$_upd_gen/$_upd_f" ]] && command -v jq >/dev/null 2>&1; then
|
||||
@ -114,7 +114,7 @@ dockerUninstallApp()
|
||||
echo ""
|
||||
echo "---- $menu_number. Removing related task history"
|
||||
echo ""
|
||||
local _tasks_dir="${containers_dir}libreportal/frontend/data/tasks"
|
||||
local _tasks_dir="$(webuiDir)/frontend/data/tasks"
|
||||
local _removed=0
|
||||
if [[ -d "$_tasks_dir" ]]; then
|
||||
for _tf in "$_tasks_dir"/task_*.json; do
|
||||
|
||||
@ -91,13 +91,33 @@ runInstallWrite() {
|
||||
# file" bug — the substitution silently failed, leaving the placeholder).
|
||||
runCfgOp() {
|
||||
local _file="${!#}"
|
||||
if [[ -n "$containers_dir" && "$_file" == "$containers_dir"* ]]; then
|
||||
if _runCfgIsContainerPath "$_file"; then
|
||||
runFileOp "$@"
|
||||
else
|
||||
runInstallOp "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# paths.sh owns pathIsContainerData (it knows every registered storage root).
|
||||
# init.sh sources THIS file directly at install time WITHOUT paths.sh, so fall
|
||||
# back to the primary root alone — at install no extra locations exist yet, so
|
||||
# the two answers agree.
|
||||
#
|
||||
# Deliberately not named pathIsContainerData: a same-named top-level definition
|
||||
# here gets indexed by generate_function_manifest.sh, and the resulting autoload
|
||||
# stub would shadow the real multi-root implementation with this primary-only
|
||||
# one — silently classifying every file on a second disk as manager-owned.
|
||||
_runCfgIsContainerPath() {
|
||||
local p="$1"
|
||||
if declare -F pathIsContainerData >/dev/null 2>&1; then
|
||||
pathIsContainerData "$p"
|
||||
return $?
|
||||
fi
|
||||
local root="${LP_CONTAINERS_DIR:-/libreportal-containers}"
|
||||
root="${root%/}"
|
||||
[[ -n "$p" && ( "$p" == "$root" || "$p" == "$root/"* ) ]]
|
||||
}
|
||||
|
||||
# Backup-engine command (borg/restic/kopia) run AS the dedicated backup user
|
||||
# ($docker_install_user), with the repo password and BORG_/RESTIC_/KOPIA_ env
|
||||
# vars carried across the privilege drop. Never root — the scoped sudoers lets
|
||||
|
||||
@ -43,7 +43,7 @@ dockerRemoveStrandedContainers()
|
||||
[[ -z "$name" || -z "$work_dir" ]] && continue
|
||||
# Only LibrePortal's own container tree, and only when the project
|
||||
# directory is provably gone.
|
||||
[[ "$work_dir" == "$containers_dir"* ]] || continue
|
||||
pathIsContainerData "$work_dir" || continue
|
||||
[[ -d "$work_dir" ]] && continue
|
||||
|
||||
if runFileOp docker rm -f "$name" >/dev/null 2>&1; then
|
||||
|
||||
@ -67,7 +67,7 @@ dockerHealthScan() {
|
||||
# $state_file, written ONLY by the throttled caller (webuiSystemHealthCheck)
|
||||
# via HEALTH_RESTART_SNAPSHOT, so the heal's rapid re-scans don't disturb the
|
||||
# baseline. One inspect over all containers (name|count|status|restarting).
|
||||
local state_file="${containers_dir}/libreportal/frontend/data/system/.health_restart_counts"
|
||||
local state_file="$(webuiDir)/frontend/data/system/.health_restart_counts"
|
||||
HEALTH_RESTART_SNAPSHOT=""
|
||||
|
||||
declare -A _prev_rc=()
|
||||
|
||||
@ -17,7 +17,7 @@ copyFile()
|
||||
# the manager-owned control plane (configs/logs/etc.) is runInstallOp.
|
||||
# Mirrors createTouch's path-based ownership; $user_name is now advisory.
|
||||
local op="runInstallOp"
|
||||
[[ "$save_dir" == "$containers_dir"* || "$save_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$save_dir" && op="runFileOp"
|
||||
|
||||
if [ "$silent_flag" == "loud" ]; then
|
||||
local result; result=$($op cp $flags_full "$file" "$save_dir")
|
||||
@ -43,7 +43,7 @@ repairStubDirForFile()
|
||||
[[ -d "$target" ]] || return 0
|
||||
|
||||
local op="runInstallOp"
|
||||
[[ "$target" == "$containers_dir"* || "$target" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$target" && op="runFileOp"
|
||||
|
||||
local name; name=$(basename "$target")
|
||||
local staged="$target.stub-repair.$$"
|
||||
|
||||
@ -9,7 +9,7 @@ copyFiles()
|
||||
|
||||
# Write as the destination's owner (see copyFile).
|
||||
local op="runInstallOp"
|
||||
[[ "$save_dir" == "$containers_dir"* || "$save_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$save_dir" && op="runFileOp"
|
||||
|
||||
local files=($($op find "$source" -type f))
|
||||
if [ ${#files[@]} -eq 0 ]; then
|
||||
|
||||
@ -21,7 +21,7 @@ createTouch()
|
||||
local file_dir=$(dirname "$clean_file")
|
||||
|
||||
local op="runInstallOp"
|
||||
if [[ "$clean_file" == "$containers_dir"* || "$clean_file" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]]; then
|
||||
if pathIsContainerData "$clean_file"; then
|
||||
op="runFileOp"
|
||||
fi
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ moveFile()
|
||||
if [ -e "$file" ]; then
|
||||
# Move as the destination's owner — no root, no chown (see copyFile).
|
||||
local op="runInstallOp"
|
||||
[[ "$save_dir" == "$containers_dir"* || "$save_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$save_dir" && op="runFileOp"
|
||||
local result; result=$($op mv "$file" "$save_dir")
|
||||
checkSuccess "Moving $file_name to $save_dir"
|
||||
else
|
||||
|
||||
@ -8,8 +8,8 @@ copyFolder()
|
||||
local user_name="$3" # advisory — the destination path determines the owner
|
||||
|
||||
# Write as the destination's owner — no root, no chown (see copyFile).
|
||||
if [[ "$save_dir" == "$containers_dir"* || "$save_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]]; then
|
||||
if [[ "$folder" == "$containers_dir"* || "$folder" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]]; then
|
||||
if pathIsContainerData "$save_dir"; then
|
||||
if pathIsContainerData "$folder"; then
|
||||
# container -> container: same owner (dockerinstall), a plain cp works.
|
||||
local result; result=$(runFileOp cp -rf "$folder" "$save_dir")
|
||||
else
|
||||
|
||||
@ -8,7 +8,7 @@ copyFolders()
|
||||
|
||||
# Write as the destination's owner — no root, no chown (see copyFile).
|
||||
local op="runInstallOp"
|
||||
[[ "$save_dir" == "$containers_dir"* || "$save_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]] && op="runFileOp"
|
||||
pathIsContainerData "$save_dir" && op="runFileOp"
|
||||
|
||||
local subdirs=($(find "$source" -mindepth 1 -maxdepth 1 -type d))
|
||||
if [ ${#subdirs[@]} -eq 0 ]; then
|
||||
|
||||
@ -14,7 +14,7 @@ createFolders()
|
||||
# AS that user via runFileOp — creating it as the right owner avoids a
|
||||
# chown-to-another-user the unprivileged runtime can't do. Mirrors
|
||||
# createTouch; the $user_name hint is advisory for these paths.
|
||||
if [[ "$clean_dir" == "$containers_dir"* || "$clean_dir" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]]; then
|
||||
if pathIsContainerData "$clean_dir"; then
|
||||
if [ ! -d "$dir_path" ]; then
|
||||
local result; result=$(runFileOp mkdir -p "$dir_path")
|
||||
[ "$silent_flag" == "loud" ] && checkSuccess "Creating $folder_name directory"
|
||||
|
||||
@ -125,7 +125,7 @@ setupApplyFinalize()
|
||||
# failed app's own task row is already red; the WebUI watcher is what gates
|
||||
# the "your install is ready" hand-off on this same group-level result.
|
||||
if [[ -n "$setup_group" ]]; then
|
||||
local tasks_dir="${containers_dir}libreportal/frontend/data/tasks"
|
||||
local tasks_dir="$(webuiDir)/frontend/data/tasks"
|
||||
local total=0 failed=0 failed_names="" f
|
||||
if [[ -d "$tasks_dir" ]]; then
|
||||
for f in "$tasks_dir"/task_*.json; do
|
||||
|
||||
@ -1,21 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
SETUP_LOCK_FILE="${containers_dir}libreportal/frontend/data/.setup_complete"
|
||||
# Resolved on call, not at source time: this file can be sourced by the lazy
|
||||
# loader before paths.sh has run, and a source-time expansion would bake an
|
||||
# empty root into an absolute-looking path.
|
||||
setupLockFile()
|
||||
{
|
||||
printf '%s' "$(webuiDir)/frontend/data/.setup_complete"
|
||||
}
|
||||
|
||||
isSetupWizardComplete()
|
||||
{
|
||||
[[ -f "$SETUP_LOCK_FILE" ]]
|
||||
[[ -f "$(setupLockFile)" ]]
|
||||
}
|
||||
|
||||
setupWizardMarkComplete()
|
||||
{
|
||||
# .setup_complete lives in the docker-install-owned frontend/data -> runFileOp
|
||||
# (created as that user; no root, no chown).
|
||||
runFileOp touch "$SETUP_LOCK_FILE" 2>/dev/null
|
||||
runFileOp chmod 644 "$SETUP_LOCK_FILE" 2>/dev/null
|
||||
runFileOp touch "$(setupLockFile)" 2>/dev/null
|
||||
runFileOp chmod 644 "$(setupLockFile)" 2>/dev/null
|
||||
}
|
||||
|
||||
setupWizardReset()
|
||||
{
|
||||
runFileOp rm -f "$SETUP_LOCK_FILE" 2>/dev/null
|
||||
runFileOp rm -f "$(setupLockFile)" 2>/dev/null
|
||||
}
|
||||
|
||||
@ -915,6 +915,7 @@ declare -gA LP_FN_MAP=(
|
||||
[runAsManager]="docker/command/run_privileged.sh"
|
||||
[runBackupOp]="docker/command/run_privileged.sh"
|
||||
[runBinInstall]="docker/command/run_privileged.sh"
|
||||
[_runCfgIsContainerPath]="docker/command/run_privileged.sh"
|
||||
[runCfgOp]="docker/command/run_privileged.sh"
|
||||
[runCrowdsec]="docker/command/run_privileged.sh"
|
||||
[runFileOp]="docker/command/run_privileged.sh"
|
||||
@ -951,6 +952,7 @@ declare -gA LP_FN_MAP=(
|
||||
[setupHeadscaleUser]="headscale/scripts/headscale_user.sh"
|
||||
[setupHeadscaleVariables]="network/variables/headscale_variables.sh"
|
||||
[setupLocalDnsRewrites]="network/dns/setup_local_dns.sh"
|
||||
[setupLockFile]="setup/setup_lock.sh"
|
||||
[setupTaskDir]="task/crontab_task_processor.sh"
|
||||
[setupWizardMarkComplete]="setup/setup_lock.sh"
|
||||
[setupWizardReset]="setup/setup_lock.sh"
|
||||
@ -2097,6 +2099,7 @@ declare -gA LP_FN_ROOT=(
|
||||
[runAsManager]="scripts"
|
||||
[runBackupOp]="scripts"
|
||||
[runBinInstall]="scripts"
|
||||
[_runCfgIsContainerPath]="scripts"
|
||||
[runCfgOp]="scripts"
|
||||
[runCrowdsec]="scripts"
|
||||
[runFileOp]="scripts"
|
||||
@ -2133,6 +2136,7 @@ declare -gA LP_FN_ROOT=(
|
||||
[setupHeadscaleUser]="containers"
|
||||
[setupHeadscaleVariables]="scripts"
|
||||
[setupLocalDnsRewrites]="scripts"
|
||||
[setupLockFile]="scripts"
|
||||
[setupTaskDir]="scripts"
|
||||
[setupWizardMarkComplete]="scripts"
|
||||
[setupWizardReset]="scripts"
|
||||
@ -2387,7 +2391,6 @@ LP_EAGER_FILES=(
|
||||
"containers:matrix/scripts/matrix_auth.sh"
|
||||
"scripts:migrate/migrate_url_rewrite.sh"
|
||||
"containers:nextcloud/scripts/nextcloud_upgrade_hooks.sh"
|
||||
"scripts:setup/setup_lock.sh"
|
||||
"scripts:source/artifacts.sh"
|
||||
"scripts:task/crontab_check_processor.sh"
|
||||
"scripts:task/crontab_task_processor.sh"
|
||||
@ -3316,6 +3319,7 @@ runAppCfg() { unset -f runAppCfg; __lpAutoload "${install_scripts_dir}docker/com
|
||||
runAsManager() { unset -f runAsManager; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runAsManager "$@"; }
|
||||
runBackupOp() { unset -f runBackupOp; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runBackupOp "$@"; }
|
||||
runBinInstall() { unset -f runBinInstall; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runBinInstall "$@"; }
|
||||
_runCfgIsContainerPath() { unset -f _runCfgIsContainerPath; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; _runCfgIsContainerPath "$@"; }
|
||||
runCfgOp() { unset -f runCfgOp; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runCfgOp "$@"; }
|
||||
runCrowdsec() { unset -f runCrowdsec; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runCrowdsec "$@"; }
|
||||
runFileOp() { unset -f runFileOp; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runFileOp "$@"; }
|
||||
@ -3352,6 +3356,7 @@ setupHeadscaleRemote() { unset -f setupHeadscaleRemote; __lpAutoload "${install_
|
||||
setupHeadscaleUser() { unset -f setupHeadscaleUser; __lpAutoload "${install_containers_dir}headscale/scripts/headscale_user.sh"; setupHeadscaleUser "$@"; }
|
||||
setupHeadscaleVariables() { unset -f setupHeadscaleVariables; __lpAutoload "${install_scripts_dir}network/variables/headscale_variables.sh"; setupHeadscaleVariables "$@"; }
|
||||
setupLocalDnsRewrites() { unset -f setupLocalDnsRewrites; __lpAutoload "${install_scripts_dir}network/dns/setup_local_dns.sh"; setupLocalDnsRewrites "$@"; }
|
||||
setupLockFile() { unset -f setupLockFile; __lpAutoload "${install_scripts_dir}setup/setup_lock.sh"; setupLockFile "$@"; }
|
||||
setupTaskDir() { unset -f setupTaskDir; __lpAutoload "${install_scripts_dir}task/crontab_task_processor.sh"; setupTaskDir "$@"; }
|
||||
setupWizardMarkComplete() { unset -f setupWizardMarkComplete; __lpAutoload "${install_scripts_dir}setup/setup_lock.sh"; setupWizardMarkComplete "$@"; }
|
||||
setupWizardReset() { unset -f setupWizardReset; __lpAutoload "${install_scripts_dir}setup/setup_lock.sh"; setupWizardReset "$@"; }
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
crontabSetupCheckProcessor()
|
||||
{
|
||||
local task_check_script="$install_scripts_dir/task/crontab_check_processor.sh"
|
||||
local task_dir="$containers_dir/libreportal/frontend/data/tasks"
|
||||
local task_dir="$(webuiDir)/frontend/data/tasks"
|
||||
|
||||
# Update TASK_DIR in the task processor script
|
||||
if [ -f "$task_check_script" ]; then
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
crontabSetupTaskProcessor()
|
||||
{
|
||||
local task_processor_script="$install_scripts_dir/task/crontab_task_processor.sh"
|
||||
local task_dir="$containers_dir/libreportal/frontend/data/tasks"
|
||||
local task_dir="$(webuiDir)/frontend/data/tasks"
|
||||
|
||||
# Update TASK_DIR in the task processor script
|
||||
if [ -f "$task_processor_script" ]; then
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# Update a specific app's status in apps.json (used for install/uninstall operations)
|
||||
webuiUpdateAppStatus() {
|
||||
local app_name="$1"
|
||||
local output_file="${containers_dir}libreportal/frontend/data/apps/generated/apps.json"
|
||||
local output_file="$(webuiDir)/frontend/data/apps/generated/apps.json"
|
||||
|
||||
if [[ -z "$app_name" ]]; then
|
||||
isError "app_name parameter required for webuiUpdateAppStatus"
|
||||
|
||||
@ -33,7 +33,7 @@ _webuiReadServiceTags() {
|
||||
webuiGenerateLibrePortalConfig() {
|
||||
local testing_mode="$1"
|
||||
local specific_app="$2"
|
||||
local output_file="${containers_dir}libreportal/frontend/data/apps/generated/apps.json"
|
||||
local output_file="$(webuiDir)/frontend/data/apps/generated/apps.json"
|
||||
local first_app=true
|
||||
local app_count=0
|
||||
|
||||
@ -162,7 +162,7 @@ EOF
|
||||
icon_file="$app_name.png"
|
||||
fi
|
||||
if [[ -n "$icon_file" ]]; then
|
||||
local icons_apps_dir="${containers_dir}libreportal/frontend/core/icons/apps"
|
||||
local icons_apps_dir="$(webuiDir)/frontend/core/icons/apps"
|
||||
runFileOp mkdir -p "$icons_apps_dir"
|
||||
runFileWrite "$icons_apps_dir/$icon_file" < "$dir/$icon_file" 2>/dev/null
|
||||
fi
|
||||
|
||||
@ -7,7 +7,7 @@ webuiPatchAppConfigJson() {
|
||||
local app_name="$1"
|
||||
[[ -z "$app_name" ]] && return 1
|
||||
|
||||
local apps_json="${containers_dir}libreportal/frontend/data/apps/generated/apps.json"
|
||||
local apps_json="$(webuiDir)/frontend/data/apps/generated/apps.json"
|
||||
[[ ! -f "$apps_json" ]] && return 1
|
||||
|
||||
local deployed_cfg="${containers_dir}${app_name}/${app_name}.config"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Generates apps-services.json from database
|
||||
webuiGenerateAppsServicesConfig() {
|
||||
local testing_mode="$1"
|
||||
local output_file="${containers_dir}libreportal/frontend/data/apps/generated/apps-services.json"
|
||||
local output_file="$(webuiDir)/frontend/data/apps/generated/apps-services.json"
|
||||
local first_service=true
|
||||
local service_count=0
|
||||
|
||||
@ -81,8 +81,8 @@ EOF
|
||||
# source IP of the default route) is what LAN/VPN clients dial,
|
||||
# and matches the host APP_URL is stamped with.
|
||||
local server_ip=""
|
||||
if [[ -f "${containers_dir}libreportal/config/generated/configs.json" ]]; then
|
||||
server_ip=$(grep -o '"CFG_SERVER_IP":[[:space:]]*"[^"]*"' "${containers_dir}libreportal/config/generated/configs.json" | cut -d'"' -f4)
|
||||
if [[ -f "$(webuiDir)/config/generated/configs.json" ]]; then
|
||||
server_ip=$(grep -o '"CFG_SERVER_IP":[[:space:]]*"[^"]*"' "$(webuiDir)/config/generated/configs.json" | cut -d'"' -f4)
|
||||
fi
|
||||
[[ -z "$server_ip" ]] && server_ip="${local_ip_v4:-localhost}"
|
||||
[[ -z "$server_ip" ]] && server_ip="localhost"
|
||||
|
||||
@ -47,7 +47,7 @@ webuiGenerateAppsToolsConfig() {
|
||||
return $?
|
||||
fi
|
||||
|
||||
local output_file="${containers_dir}libreportal/frontend/data/apps/generated/apps-tools.json"
|
||||
local output_file="$(webuiDir)/frontend/data/apps/generated/apps-tools.json"
|
||||
local tmp="$(mktemp)"
|
||||
|
||||
runFileOp mkdir -p "$(dirname "$output_file")"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
webuiGenerateBackupAppStatus()
|
||||
{
|
||||
local app_name="${1:-}"
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated/apps"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated/apps"
|
||||
runFileOp mkdir -p "$output_dir"
|
||||
|
||||
# Resolve the app list: a single app (direct call — e.g. right after that
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
webuiGenerateBackupDashboard()
|
||||
{
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
local output_file="$output_dir/dashboard.json"
|
||||
local temp_file="${output_file}.tmp.$$"
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
webuiGenerateBackupEngines()
|
||||
{
|
||||
local src_dir="$install_scripts_dir/backup/engines"
|
||||
local out_dir="$containers_dir/libreportal/frontend/data/backup/generated/engines"
|
||||
local out_dir="$(webuiDir)/frontend/data/backup/generated/engines"
|
||||
runFileOp mkdir -p "$out_dir"
|
||||
|
||||
if [[ ! -d "$src_dir" ]]; then
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
webuiGenerateBackupLocations()
|
||||
{
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
local output_file="$output_dir/locations.json"
|
||||
local temp_file="${output_file}.tmp.$$"
|
||||
runFileOp mkdir -p "$output_dir"
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
webuiGenerateBackupMigrate()
|
||||
{
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
local output_file="$output_dir/migrate.json"
|
||||
|
||||
runFileOp mkdir -p "$output_dir"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
webuiGenerateBackupPasswords()
|
||||
{
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
local output_file="$output_dir/passwords.txt"
|
||||
local temp_file="${output_file}.tmp.$$"
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
webuiGenerateBackupSchema()
|
||||
{
|
||||
local out_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local out_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
local out_file="$out_dir/schema.json"
|
||||
runFileOp mkdir -p "$out_dir"
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
webuiGenerateBackupSnapshots()
|
||||
{
|
||||
local scope="${1:-all}"
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/backup/generated"
|
||||
runFileOp mkdir -p "$output_dir"
|
||||
|
||||
local indices=()
|
||||
|
||||
@ -14,7 +14,7 @@ createTaskFile() {
|
||||
fi
|
||||
|
||||
# Set task directory
|
||||
local task_dir="${containers_dir}libreportal/frontend/data/tasks"
|
||||
local task_dir="$(webuiDir)/frontend/data/tasks"
|
||||
|
||||
# Ensure task directory exists (container-owned WebUI data tree -> runFileOp)
|
||||
if [ ! -d "$task_dir" ]; then
|
||||
|
||||
@ -78,7 +78,7 @@ webuiGenerateSystemConfigs() {
|
||||
fi
|
||||
}
|
||||
|
||||
local output_file="${containers_dir}libreportal/frontend/data/config/generated/configs.json"
|
||||
local output_file="$(webuiDir)/frontend/data/config/generated/configs.json"
|
||||
local temp_file="$(mktemp)"
|
||||
|
||||
runFileOp mkdir -p "$(dirname "$output_file")"
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
webuiGeneratePeers()
|
||||
{
|
||||
local output_dir="$containers_dir/libreportal/frontend/data/peers/generated"
|
||||
local output_dir="$(webuiDir)/frontend/data/peers/generated"
|
||||
local output_file="$output_dir/peers.json"
|
||||
|
||||
runFileOp mkdir -p "$output_dir"
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
webuiGenerateSshAccess()
|
||||
{
|
||||
local out_dir="$containers_dir/libreportal/frontend/data/ssh"
|
||||
local out_dir="$(webuiDir)/frontend/data/ssh"
|
||||
local out_file="$out_dir/access.json"
|
||||
runFileOp mkdir -p "$out_dir"
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ webuiSystemDisk() {
|
||||
fi
|
||||
|
||||
# Create system info directory if it doesn't exist
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
createFolders "quiet" $sudo_user_name "$system_dir"
|
||||
|
||||
# Create temp file first, then atomic move
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
webuiSystemHealthCheck() {
|
||||
local force_flag="$1"
|
||||
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
local final_file="${system_dir}/health_status.json"
|
||||
local stamp_file="${system_dir}/.health_check_stamp"
|
||||
local heal_stamp="${system_dir}/.health_heal_stamp"
|
||||
|
||||
@ -31,7 +31,7 @@ webuiSystemInfo() {
|
||||
local kernel_version=$(uname -r)
|
||||
|
||||
# Create system info directory if it doesn't exist
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
createFolders "quiet" $sudo_user_name "$system_dir"
|
||||
|
||||
# Create temp file first, then atomic move
|
||||
|
||||
@ -23,7 +23,7 @@ webuiSystemMemory() {
|
||||
local mem_text="$mem_used_gb GB / $mem_total_gb GB - $mem_percent%"
|
||||
|
||||
# Create system info directory if it doesn't exist
|
||||
local system_dir="${containers_dir}libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
createFolders "quiet" $sudo_user_name "$system_dir"
|
||||
|
||||
# Create temp file first, then atomic move
|
||||
|
||||
@ -27,7 +27,7 @@ _metricsReadCpu() {
|
||||
}
|
||||
|
||||
webuiSystemMetrics() {
|
||||
local system_dir="${containers_dir}libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
createFolders "quiet" "$sudo_user_name" "$system_dir"
|
||||
|
||||
local now_epoch; now_epoch=$(date +%s)
|
||||
@ -209,7 +209,7 @@ EOF
|
||||
# run per CFG_APP_STORAGE_INTERVAL (default 10 min) via the .stamp idiom used by
|
||||
# the update/verify checks above. Pass "force" to bypass it.
|
||||
webuiSystemAppStorage() {
|
||||
local system_dir="${containers_dir}libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
createFolders "quiet" "$sudo_user_name" "$system_dir"
|
||||
|
||||
local final_file="$system_dir/app_storage.json"
|
||||
@ -304,7 +304,7 @@ webuiSystemAppStorage() {
|
||||
# compose project label fall back to their container name so nothing is lost.
|
||||
webuiSystemApps() {
|
||||
local now_epoch="$1" now_iso="$2" system_dir="$3"
|
||||
[[ -z "$system_dir" ]] && system_dir="${containers_dir}libreportal/frontend/data/system"
|
||||
[[ -z "$system_dir" ]] && system_dir="$(webuiDir)/frontend/data/system"
|
||||
command -v docker &>/dev/null || return 0
|
||||
|
||||
# name|project|state|status for every container (running or not)
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
webuiSystemNetworkCheck() {
|
||||
local force_flag="$1"
|
||||
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
local final_file="${system_dir}/network_status.json"
|
||||
local stamp_file="${system_dir}/.network_check_stamp"
|
||||
local interval="${CFG_NETWORK_CHECK_INTERVAL:-300}"
|
||||
|
||||
@ -52,7 +52,7 @@ webuiSystemUpdateCheck() {
|
||||
local force_flag="$1"
|
||||
|
||||
local repo_dir="${script_dir}"
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
local final_file="${system_dir}/update_status.json"
|
||||
local stamp_file="${system_dir}/.update_check_stamp"
|
||||
# How long (seconds) a fetch result stays "fresh" before we hit the network
|
||||
@ -267,7 +267,7 @@ EOF
|
||||
webuiSystemVerify() {
|
||||
local force_flag="$1"
|
||||
|
||||
local system_dir="$containers_dir/libreportal/frontend/data/system"
|
||||
local system_dir="$(webuiDir)/frontend/data/system"
|
||||
local final_file="${system_dir}/verify_status.json"
|
||||
local stamp_file="${system_dir}/.verify_check_stamp"
|
||||
local interval="${CFG_VERIFY_CHECK_INTERVAL:-86400}"
|
||||
|
||||
@ -355,7 +355,7 @@ updaterDisplayVersion() {
|
||||
}
|
||||
|
||||
webuiUpdaterScan() {
|
||||
local out_dir="$containers_dir/libreportal/frontend/data/updater/generated"
|
||||
local out_dir="$(webuiDir)/frontend/data/updater/generated"
|
||||
runFileOp mkdir -p "$out_dir" 2>/dev/null || mkdir -p "$out_dir" 2>/dev/null
|
||||
|
||||
local now; now="$(date -Iseconds 2>/dev/null || date)"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
# the leftover lock would otherwise wedge EVERY future refresh. No single refresh
|
||||
# runs anywhere near this long, so a lock older than the threshold is a leftover.
|
||||
webuiCheckUpdateLock() {
|
||||
local lock_file="$containers_dir/libreportal/frontend/data/updater.lock"
|
||||
local lock_file="$(webuiDir)/frontend/data/updater.lock"
|
||||
local stale_after=900 # seconds (15 min); far longer than any real refresh
|
||||
|
||||
if [ ! -f "$lock_file" ]; then
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Creates update lock file to prevent concurrent updates
|
||||
|
||||
webuiCreateUpdateLock() {
|
||||
local lock_file="$containers_dir/libreportal/frontend/data/updater.lock"
|
||||
local lock_file="$(webuiDir)/frontend/data/updater.lock"
|
||||
|
||||
# Create lock file with timestamp and process ID. The lock lives in the
|
||||
# dockerinstall-owned WebUI data dir, so write it as the path owner.
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Removes setup lock file after update completion
|
||||
|
||||
webuiRemoveSetupLock() {
|
||||
local lock_file="$containers_dir/libreportal/frontend/data/setup.lock"
|
||||
local lock_file="$(webuiDir)/frontend/data/setup.lock"
|
||||
|
||||
if [ -f "$lock_file" ]; then
|
||||
runFileOp rm -f "$lock_file"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Removes update lock file after update completion
|
||||
|
||||
webuiRemoveUpdateLock() {
|
||||
local lock_file="$containers_dir/libreportal/frontend/data/updater.lock"
|
||||
local lock_file="$(webuiDir)/frontend/data/updater.lock"
|
||||
|
||||
if [ -f "$lock_file" ]; then
|
||||
runFileOp rm -f "$lock_file"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
webuiCreateLogsFolders()
|
||||
{
|
||||
local log_dir="${containers_dir}libreportal/frontend/logs"
|
||||
local log_dir="$(webuiDir)/frontend/logs"
|
||||
local apps_dir="${log_dir}/apps"
|
||||
if [ ! -d "$apps_dir" ]; then
|
||||
local result; result=$(createFolders "loud" $sudo_user_name $log_dir $apps_dir)
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Ensures essential task system files exist for LibrePortal task management
|
||||
|
||||
webuiEnsureTaskFiles() {
|
||||
local task_dir="${containers_dir}libreportal/frontend/data/tasks"
|
||||
local task_dir="$(webuiDir)/frontend/data/tasks"
|
||||
|
||||
# Create tasks directory if it doesn't exist
|
||||
if [ ! -d "$task_dir" ]; then
|
||||
|
||||
@ -13,7 +13,7 @@ webuiSyncAppIcon() {
|
||||
local app_name="$1"
|
||||
[[ -z "$app_name" ]] && return 1
|
||||
|
||||
local icons_dir="${containers_dir}libreportal/frontend/core/icons/apps"
|
||||
local icons_dir="$(webuiDir)/frontend/core/icons/apps"
|
||||
runFileOp mkdir -p "$icons_dir"
|
||||
|
||||
# Icons live in the install template dir — copy_build_context.sh
|
||||
@ -65,7 +65,7 @@ webuiSyncAppIcons() {
|
||||
# Only ever removes icons it can match to a missing template, never anything
|
||||
# else in the directory.
|
||||
webuiPruneAppIcons() {
|
||||
local icons_dir="${containers_dir}libreportal/frontend/core/icons/apps"
|
||||
local icons_dir="$(webuiDir)/frontend/core/icons/apps"
|
||||
[[ -d "$icons_dir" ]] || return 0
|
||||
[[ -d "$install_containers_dir" ]] || return 0
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ webuiUpdateAppLog()
|
||||
local type=$2 # install or uninstall
|
||||
|
||||
# Create logs directory if it doesn't exist
|
||||
local log_dir="${containers_dir}libreportal/frontend/logs"
|
||||
local log_dir="$(webuiDir)/frontend/logs"
|
||||
local apps_dir="${log_dir}/apps"
|
||||
if [ ! -d "$apps_dir" ]; then
|
||||
local result; result=$(createFolders "loud" $sudo_user_name $log_dir $apps_dir)
|
||||
|
||||
@ -13,7 +13,7 @@ atomicWriteWebUI() {
|
||||
# can write the dockerinstall-owned WebUI/app files. Temp + rename share the
|
||||
# target's directory, so the mv stays atomic (same filesystem, same owner).
|
||||
local op="runInstallOp" wop="runInstallWrite"
|
||||
if [[ "$target_file" == "$containers_dir"* || "$target_file" == "${LP_CONTAINERS_DIR:-/libreportal-containers}"/* ]]; then
|
||||
if pathIsContainerData "$target_file"; then
|
||||
op="runFileOp"; wop="runFileWrite"
|
||||
fi
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ installLibrePortalImageWebUI()
|
||||
# libreportal.config as a Docker-created directory. The tar copy below can't
|
||||
# extract a file over a directory ("Cannot open: File exists") and aborts the
|
||||
# whole source copy, so clear the stub first.
|
||||
repairStubDirForFile "$containers_dir/libreportal/libreportal.config" "loud"
|
||||
repairStubDirForFile "$(webuiDir)/libreportal.config" "loud"
|
||||
|
||||
local result; result=$(copyFolder "$install_containers_dir/libreportal" "$containers_dir" "$sudo_user_name")
|
||||
checkSuccess "Copy the LibrePortal to the containers folder"
|
||||
@ -40,6 +40,6 @@ installLibrePortalImageWebUI()
|
||||
fi
|
||||
|
||||
isNotice "Building libreportal-service image, this may take a while..."
|
||||
local result; result=$(runFileOp docker build -t libreportal-service -f $containers_dir/libreportal/Dockerfile $containers_dir/libreportal >/dev/null 2>&1)
|
||||
local result; result=$(runFileOp docker build -t libreportal-service -f $(webuiDir)/Dockerfile $(webuiDir) >/dev/null 2>&1)
|
||||
checkSuccess "Built LibrePortal WebUI Docker image"
|
||||
}
|
||||
@ -14,7 +14,7 @@ installLibrePortalWebUITaskService()
|
||||
[[ "$CFG_REQUIREMENT_WEBUI_SERVICE" == "true" ]] || return 0
|
||||
|
||||
local task_processor_script="$install_scripts_dir/task/crontab_task_processor.sh"
|
||||
local task_dir="$containers_dir/libreportal/frontend/data/tasks"
|
||||
local task_dir="$(webuiDir)/frontend/data/tasks"
|
||||
|
||||
# Point the processor at the task dir (idempotent). This edits the
|
||||
# manager-owned install tree, so no privilege is needed.
|
||||
|
||||
@ -49,7 +49,7 @@ _lpRegenOrphanedApp() {
|
||||
|
||||
lpRegenWebui() {
|
||||
local force="$1"
|
||||
local gen="${containers_dir}libreportal/frontend/data/apps/generated"
|
||||
local gen="$(webuiDir)/frontend/data/apps/generated"
|
||||
local apps_json="$gen/apps.json"
|
||||
local tools_json="$gen/apps-tools.json"
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ webuiLibrePortalUpdate() {
|
||||
checkSuccess "Generated system configurations..."
|
||||
|
||||
# Generate categories
|
||||
local result; result=$(webuiCreateCategories $containers_dir/libreportal/frontend/data)
|
||||
local result; result=$(webuiCreateCategories $(webuiDir)/frontend/data)
|
||||
checkSuccess "Generated app and config categories..."
|
||||
|
||||
# Generate LibrePortal app configuration
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user