LibrePortal/scripts/setup/setup_apply.sh
librelad 875a60f90f LibrePortal v0.1.0 — initial release
A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys,
Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun
VPN routing, and a web dashboard to manage it all.

Free & open forever to self-host; optional paid hosted services fund it.
See PROMISE.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-21 20:37:54 +01:00

150 lines
5.0 KiB
Bash

#!/bin/bash
setupApplyConfig()
{
local payload_b64="$1"
if [[ -z "$payload_b64" ]]; then
isError "setupApplyConfig: no payload provided"
return 1
fi
local payload
payload=$(echo "$payload_b64" | base64 -d 2>/dev/null)
if [[ -z "$payload" ]]; then
isError "setupApplyConfig: failed to decode payload"
return 1
fi
isHeader "Applying Setup Wizard Configuration"
local install_name=$(echo "$payload" | jq -r '.install_name // empty')
local timezone=$(echo "$payload" | jq -r '.timezone // empty')
local traefik_email=$(echo "$payload" | jq -r '.traefik_email // empty')
local domains_json=$(echo "$payload" | jq -c '.domains // []')
if [[ -n "$install_name" ]]; then
updateConfigOption "CFG_INSTALL_NAME" "$install_name"
isSuccessful "Install name set to '$install_name'"
fi
if [[ -n "$timezone" ]]; then
updateConfigOption "CFG_TIMEZONE" "$timezone"
isSuccessful "Timezone set to '$timezone'"
fi
local domains_count=$(echo "$domains_json" | jq -r 'length')
if [[ "$domains_count" -gt 0 ]]; then
local i=0
while [[ $i -lt $domains_count && $i -lt 9 ]]; do
local d=$(echo "$domains_json" | jq -r ".[$i]")
updateConfigOption "CFG_DOMAIN_$((i+1))" "$d"
isSuccessful "Domain $((i+1)) set to '$d'"
((i++))
done
fi
if [[ -n "$traefik_email" && "$traefik_email" != "null" ]]; then
# CFG_TRAEFIK_EMAIL lives in containers/traefik/traefik.config, not in
# the system $configs_dir, so findConfigFileForOption can't auto-locate
# it. Point updateConfigOption at the source file directly. Traefik
# may not be installed yet at this point — config gets copied from
# install_containers_dir into containers_dir during the app-install
# task, so we always update the source.
local traefik_config_file="$install_containers_dir/traefik/traefik.config"
if [[ -f "$traefik_config_file" ]]; then
updateConfigOption "CFG_TRAEFIK_EMAIL" "$traefik_email" "$traefik_config_file"
isSuccessful "Traefik LetsEncrypt email set to '$traefik_email'"
else
isNotice "Traefik source config not found at $traefik_config_file; skipping email write."
fi
fi
# App sub-options are no longer handled here. The setup-routes backend
# folds payload.appOptions into each install command's config_variables
# arg (CFG_REQUIREMENT_<APP>_<OPT>=<bool>) and dockerInstallApp writes
# them into the template config before install<App> runs.
sourceScanFiles "libreportal_configs"
isSuccessful "Configuration written. Selected apps will install next."
}
setupApplyFinalize()
{
isNotice "Initializing backup engine..."
if declare -f installResticHost >/dev/null 2>&1; then
installResticHost
else
isNotice "installResticHost not loaded; backup repos will init on first backup."
fi
isNotice "Refreshing WebUI data snapshots so the config page reflects wizard changes..."
if declare -f webuiLibrePortalUpdate >/dev/null 2>&1; then
webuiLibrePortalUpdate
else
isNotice "webuiLibrePortalUpdate not loaded; skipping refresh."
fi
if declare -f webuiGenerateBackupLocations >/dev/null 2>&1; then
webuiGenerateBackupLocations
webuiGenerateBackupDashboard
webuiGenerateBackupSnapshots all
webuiGenerateBackupAppStatus
fi
setupWizardMarkComplete
isSuccessful "Setup Wizard complete — your install is configured and ready."
}
setupApply()
{
setupApplyConfig "$1" || return 1
local payload=$(echo "$1" | base64 -d 2>/dev/null)
local apps_json=$(echo "$payload" | jq -c '.apps // []')
local apps_count=$(echo "$apps_json" | jq -r 'length')
if [[ "$apps_count" -gt 0 ]]; then
isHeader "Installing Selected Apps"
local i=0
while [[ $i -lt $apps_count ]]; do
local app_name=$(echo "$apps_json" | jq -r ".[$i]")
isNotice "[$((i+1))/$apps_count] Installing $app_name..."
dockerInstallApp "$app_name"
((i++))
done
fi
setupApplyFinalize
}
setupGenerateName()
{
if declare -f generateInstallName >/dev/null 2>&1; then
generateInstallName
else
echo "QuantumOtter"
fi
}
setupCheckDomainPointsHere()
{
local domain="$1"
if [[ -z "$domain" ]]; then
echo '{"matches":false,"error":"no domain"}'
return 1
fi
local server_ip
server_ip=$(dig +short +time=3 +tries=1 myip.opendns.com @resolver1.opendns.com 2>/dev/null | head -1)
[[ -z "$server_ip" ]] && server_ip=$(hostname -I 2>/dev/null | awk '{print $1}')
local domain_ip
domain_ip=$(dig +short +time=3 +tries=1 "$domain" A 2>/dev/null | head -1)
local matches="false"
[[ -n "$server_ip" && "$server_ip" == "$domain_ip" ]] && matches="true"
printf '{"matches":%s,"server_ip":"%s","domain_ip":"%s"}\n' "$matches" "$server_ip" "$domain_ip"
}