refactor(config): updater knobs -> configs/webui/webui_updater; fix config heal/reconcile gaps
Move the WebUI-updater settings out of general_terminal into their own
advanced webui-category file (webui_logs precedent): new
configs/webui/webui_updater holds CFG_UPDATER_SCAN_INTERVAL and the
migrated CFG_HOTFIX_AUTO, listed in webui/.category.
The move only reaches existing installs if the config convergence
machinery works, and three pieces of it silently didn't:
- checkConfigFilesMissingFiles walked a stale hardcoded category list
('general features network' — features doesn't exist; webui/backup/
security never healed). Derive the categories from the template tree
instead, and heal .category metadata too: copy it when absent and
merge missing SUBCATEGORY_ORDER entries when present, so healed files
actually appear in the WebUI Config editor. core_categories removed.
- Option reconciliation never touched ANY nested config file: configs_dir
carries a trailing slash, so rel stripping missed ('configs//'), the
template lookup failed, and reconcileConfigFile early-returned for
every file. Strip the slash before matching.
- reconcileConfigFile's AUTO_DELETE=false branch read a never-populated
live_line array, losing the dropped keys it promised to keep. Populate
it alongside live_value.
Also exclude *.bak from config sourcing (reconciliation writes <file>.bak
next to live configs — now that it runs, sourcing backups would resurrect
deleted keys), and add 'libreportal config check' as a non-interactive
front door to the converge pass (was only reachable via install flows and
the interactive menu).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
5b437c0c52
commit
7c28007779
@ -2,8 +2,6 @@
|
|||||||
# Terminal - System utilities and advanced settings **ADVANCED**
|
# Terminal - System utilities and advanced settings **ADVANCED**
|
||||||
# ================================================================================
|
# ================================================================================
|
||||||
CFG_UPDATER_CHECK=60 # Update Check Interval - Hours between system update checks
|
CFG_UPDATER_CHECK=60 # Update Check Interval - Hours between system update checks
|
||||||
CFG_HOTFIX_AUTO=security-breakage # Hotfix Auto-Apply - Which signed hotfix severities apply automatically on the update check [security-breakage|all|off]
|
|
||||||
CFG_UPDATER_SCAN_INTERVAL=30 # App Scan Interval - Minutes between automatic app update/CVE/improvement scans (0 disables)
|
|
||||||
CFG_SWAPFILE_SIZE=2G # Swap File Size - Size of swap file for memory management
|
CFG_SWAPFILE_SIZE=2G # Swap File Size - Size of swap file for memory management
|
||||||
CFG_GENERATED_PASS_LENGTH=14 # Password Length - Length for auto generated passwords
|
CFG_GENERATED_PASS_LENGTH=14 # Password Length - Length for auto generated passwords
|
||||||
CFG_GENERATED_USER_LENGTH=8 # Username Length - Length for auto generated usernames
|
CFG_GENERATED_USER_LENGTH=8 # Username Length - Length for auto generated usernames
|
||||||
|
|||||||
@ -2,4 +2,4 @@ TITLE=WebUI
|
|||||||
DESCRIPTION=Web interface settings and preferences
|
DESCRIPTION=Web interface settings and preferences
|
||||||
ICON=webui
|
ICON=webui
|
||||||
ORDER=2
|
ORDER=2
|
||||||
SUBCATEGORY_ORDER=webui_logins,webui_logs
|
SUBCATEGORY_ORDER=webui_logins,webui_logs,webui_updater
|
||||||
|
|||||||
5
configs/webui/webui_updater
Normal file
5
configs/webui/webui_updater
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# ================================================================================
|
||||||
|
# WebUI Updater - Automatic app update, CVE & improvement scanning **ADVANCED**
|
||||||
|
# ================================================================================
|
||||||
|
CFG_UPDATER_SCAN_INTERVAL=30 # App Scan Interval - Minutes between automatic app update/CVE/improvement scans. 0 disables.
|
||||||
|
CFG_HOTFIX_AUTO=security-breakage # Hotfix Auto-Apply - Which signed hotfix severities apply automatically on the update check [security-breakage|all|off]
|
||||||
@ -14,6 +14,16 @@ cliHandleConfigCommands()
|
|||||||
configUpdateBatch "$encoded_pairs"
|
configUpdateBatch "$encoded_pairs"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
"check")
|
||||||
|
# Converge live configs on the install templates: copy any missing
|
||||||
|
# files / categories (and surface them to the WebUI Config editor
|
||||||
|
# via .category), then reconcile the options inside each file —
|
||||||
|
# add new keys, drop removed ones, refresh comments, keep the
|
||||||
|
# user's values. Read-and-converge; safe to run any time.
|
||||||
|
checkConfigFilesMissingFiles
|
||||||
|
checkConfigFilesMissingVariables true
|
||||||
|
;;
|
||||||
|
|
||||||
"")
|
"")
|
||||||
cliShowConfigHelp
|
cliShowConfigHelp
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -5,6 +5,9 @@ cliShowConfigHelp()
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Available Config Commands:"
|
echo "Available Config Commands:"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo " libreportal config check - Converge live configs on the install templates:"
|
||||||
|
echo " copy missing files, then reconcile options in each"
|
||||||
|
echo " (add new keys, drop removed ones, keep your values)"
|
||||||
echo " libreportal config update '<encoded>' - Apply a batch of CFG_KEY=VALUE pairs"
|
echo " libreportal config update '<encoded>' - Apply a batch of CFG_KEY=VALUE pairs"
|
||||||
echo " <encoded> is pipe-separated; literal '|' in"
|
echo " <encoded> is pipe-separated; literal '|' in"
|
||||||
echo " values must be URL-encoded as %7C."
|
echo " values must be URL-encoded as %7C."
|
||||||
|
|||||||
@ -11,31 +11,66 @@ checkConfigFilesMissingFiles()
|
|||||||
local missing_files_count=0
|
local missing_files_count=0
|
||||||
local found_files_count=0
|
local found_files_count=0
|
||||||
|
|
||||||
# Check for core config categories in the new structure
|
# Walk every category the install templates define (configs/<category>/),
|
||||||
for category in "${core_categories[@]}"; do
|
# derived from the template tree itself — so a new category, or one a
|
||||||
local install_category_dir="$install_configs_dir/$category"
|
# hardcoded list would miss (webui/backup/security were), heals onto
|
||||||
local target_category_dir="$configs_dir/$category"
|
# existing installs automatically.
|
||||||
|
local install_category_dir category target_category_dir
|
||||||
if [ -d "$install_category_dir" ]; then
|
for install_category_dir in "$install_configs_dir"*/; do
|
||||||
# Create target category directory if it doesn't exist
|
[ -d "$install_category_dir" ] || continue
|
||||||
if [ ! -d "$target_category_dir" ]; then
|
category="$(basename "$install_category_dir")"
|
||||||
runInstallOp mkdir -p "$target_category_dir"
|
target_category_dir="${configs_dir%/}/$category"
|
||||||
fi
|
|
||||||
|
# Create target category directory if it doesn't exist
|
||||||
# Check each file in the install category directory
|
if [ ! -d "$target_category_dir" ]; then
|
||||||
for install_file in "$install_category_dir"/*; do
|
runInstallOp mkdir -p "$target_category_dir"
|
||||||
if [ -f "$install_file" ] && [[ ! "$install_file" =~ \.category$ ]]; then
|
fi
|
||||||
local filename=$(basename "$install_file")
|
|
||||||
local target_file="$target_category_dir/$filename"
|
# Check each file in the install category directory
|
||||||
|
local install_file
|
||||||
if [ ! -f "$target_file" ]; then
|
for install_file in "$install_category_dir"*; do
|
||||||
# Copy missing file from install directory
|
if [ -f "$install_file" ] && [[ ! "$install_file" =~ \.category$ ]]; then
|
||||||
runInstallOp cp "$install_file" "$target_file"
|
local filename=$(basename "$install_file")
|
||||||
((missing_files_count++))
|
local target_file="$target_category_dir/$filename"
|
||||||
fi
|
|
||||||
((found_files_count++))
|
if [ ! -f "$target_file" ]; then
|
||||||
|
# Copy missing file from install directory
|
||||||
|
runInstallOp cp "$install_file" "$target_file"
|
||||||
|
((missing_files_count++))
|
||||||
fi
|
fi
|
||||||
done
|
((found_files_count++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Heal the category's .category metadata too: copy it when absent (a
|
||||||
|
# brand-new category is invisible to the WebUI Config editor without
|
||||||
|
# it), and when present merge in any template SUBCATEGORY_ORDER entries
|
||||||
|
# it lacks — the editor only renders files listed there, so a healed
|
||||||
|
# config file would otherwise ship hidden. User-kept order and any
|
||||||
|
# extra local entries are preserved; new entries append.
|
||||||
|
local tmpl_cat="${install_category_dir}.category"
|
||||||
|
local live_cat="$target_category_dir/.category"
|
||||||
|
if [ -f "$tmpl_cat" ]; then
|
||||||
|
if [ ! -f "$live_cat" ]; then
|
||||||
|
runInstallOp cp "$tmpl_cat" "$live_cat"
|
||||||
|
else
|
||||||
|
local tmpl_order live_order merged entry _entries
|
||||||
|
tmpl_order="$(grep -m1 '^SUBCATEGORY_ORDER=' "$tmpl_cat" 2>/dev/null | cut -d= -f2-)"
|
||||||
|
live_order="$(runInstallOp grep -m1 '^SUBCATEGORY_ORDER=' "$live_cat" 2>/dev/null | cut -d= -f2-)"
|
||||||
|
merged="$live_order"
|
||||||
|
IFS=',' read -ra _entries <<< "$tmpl_order"
|
||||||
|
for entry in "${_entries[@]}"; do
|
||||||
|
[ -n "$entry" ] || continue
|
||||||
|
[[ ",$merged," == *",$entry,"* ]] || merged="${merged:+$merged,}$entry"
|
||||||
|
done
|
||||||
|
if [ -n "$merged" ] && [ "$merged" != "$live_order" ]; then
|
||||||
|
if runInstallOp grep -q '^SUBCATEGORY_ORDER=' "$live_cat" 2>/dev/null; then
|
||||||
|
runInstallOp sed -i "s/^SUBCATEGORY_ORDER=.*/SUBCATEGORY_ORDER=$merged/" "$live_cat"
|
||||||
|
else
|
||||||
|
printf 'SUBCATEGORY_ORDER=%s\n' "$merged" | runInstallOp tee -a "$live_cat" >/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,11 @@ checkLibrePortalConfigFilesMissingVariables()
|
|||||||
while IFS= read -r live; do
|
while IFS= read -r live; do
|
||||||
[[ -f "$live" ]] || continue
|
[[ -f "$live" ]] || continue
|
||||||
fn=$(basename "$live")
|
fn=$(basename "$live")
|
||||||
rel="${live#"$configs_dir"/}"
|
# configs_dir carries a trailing slash (paths.sh) — strip it before
|
||||||
|
# appending one, or the prefix never matches ("configs//"), rel stays
|
||||||
|
# the absolute path, the template lookup misses, and every nested
|
||||||
|
# config file silently skips reconciliation.
|
||||||
|
rel="${live#"${configs_dir%/}"/}"
|
||||||
remote="$install_configs_dir$fn"
|
remote="$install_configs_dir$fn"
|
||||||
[[ -f "$remote" ]] || remote="$install_configs_dir$rel"
|
[[ -f "$remote" ]] || remote="$install_configs_dir$rel"
|
||||||
reconcileConfigFile "$live" "$remote"
|
reconcileConfigFile "$live" "$remote"
|
||||||
|
|||||||
@ -41,13 +41,14 @@ reconcileConfigFile()
|
|||||||
[[ -f "$live" ]] || return 0
|
[[ -f "$live" ]] || return 0
|
||||||
runInstallOp test -s "$template" 2>/dev/null || return 0
|
runInstallOp test -s "$template" 2>/dev/null || return 0
|
||||||
|
|
||||||
declare -A live_value emitted
|
declare -A live_value live_line emitted
|
||||||
local line key
|
local line key
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
if [[ "$line" =~ ^(CFG_[A-Za-z0-9_]+)= ]]; then
|
if [[ "$line" =~ ^(CFG_[A-Za-z0-9_]+)= ]]; then
|
||||||
key="${BASH_REMATCH[1]}"
|
key="${BASH_REMATCH[1]}"
|
||||||
_reconcileSplitValueComment "$line"
|
_reconcileSplitValueComment "$line"
|
||||||
live_value["$key"]="$_reconcile_value"
|
live_value["$key"]="$_reconcile_value"
|
||||||
|
live_line["$key"]="$line"
|
||||||
fi
|
fi
|
||||||
done < <(runInstallOp cat "$live")
|
done < <(runInstallOp cat "$live")
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ sourceScanFiles()
|
|||||||
# echo "$load_type NEW FILE $file"
|
# echo "$load_type NEW FILE $file"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done < <(find "$folder_dir" -maxdepth 2 -type f ! -name "*.category" ! -name "config_*" ! -name ".*" -print0)
|
done < <(find "$folder_dir" -maxdepth 2 -type f ! -name "*.category" ! -name "config_*" ! -name ".*" ! -name "*.bak" -print0)
|
||||||
|
|
||||||
# Per-location backup configs live nested at depth 3
|
# Per-location backup configs live nested at depth 3
|
||||||
# (configs/backup/locations/<idx>/location.config) — source them via
|
# (configs/backup/locations/<idx>/location.config) — source them via
|
||||||
|
|||||||
@ -54,7 +54,6 @@ run_file=run.txt
|
|||||||
# Configs
|
# Configs
|
||||||
update_done=false
|
update_done=false
|
||||||
config_file_wireguard=config_wireguard
|
config_file_wireguard=config_wireguard
|
||||||
core_categories=("general" "features" "network")
|
|
||||||
|
|
||||||
# Menu
|
# Menu
|
||||||
menu_number=0
|
menu_number=0
|
||||||
Loading…
x
Reference in New Issue
Block a user