Compare commits

...

2 Commits

Author SHA1 Message Date
librelad
46843de50f Merge claude/1 2026-05-23 13:38:03 +01:00
librelad
3684ccaf68 feat(config): emit per-location field metadata into configs.json
The config generator only scanned flat per-category files, so the dynamic
CFG_BACKUP_LOC_N_* keys carried no titles/descriptions/options — the Locations
editor had to hardcode that metadata in backup-page.js. Add a pass that
descends into configs/backup/locations/<n>/location.config and emits each key
(value/title/description/options) into the config map, plus an "advanced"
flag parsed from a **ADVANCED** token in the field comment (stripped from the
user-facing description).

These keys use subcategory "backup_locations", which isn't in any category's
subcategory_order, so the generic /config page ignores them — only the custom
Locations editor consumes them. URI, SSH port, and append-only are marked
advanced. Verified: configs.json stays valid JSON and /config subcategories
are unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-23 13:38:03 +01:00
3 changed files with 80 additions and 6 deletions

View File

@ -7,10 +7,10 @@ CFG_BACKUP_LOC_1_PASSWORD=RANDOMIZEDPASSWORD1 # Repository Pas
CFG_BACKUP_LOC_1_TYPE=local # Type - Backend [local:Local / mounted path|sftp:SFTP|rest:REST|s3:S3|b2:Backblaze B2|gs:Google Cloud Storage|azure:Azure|rclone:rclone] CFG_BACKUP_LOC_1_TYPE=local # Type - Backend [local:Local / mounted path|sftp:SFTP|rest:REST|s3:S3|b2:Backblaze B2|gs:Google Cloud Storage|azure:Azure|rclone:rclone]
CFG_BACKUP_LOC_1_PATH_MODE=auto # Path Mode - Where this location stores its data [auto:Automatic (/docker/backups/<id>)|custom:Custom path] CFG_BACKUP_LOC_1_PATH_MODE=auto # Path Mode - Where this location stores its data [auto:Automatic (/docker/backups/<id>)|custom:Custom path]
CFG_BACKUP_LOC_1_PATH= # Custom Path - Filesystem path on this server (used when Path Mode = Custom) CFG_BACKUP_LOC_1_PATH= # Custom Path - Filesystem path on this server (used when Path Mode = Custom)
CFG_BACKUP_LOC_1_URI= # URI Override - Custom restic URI (leave blank to build from the fields below) CFG_BACKUP_LOC_1_URI= # URI Override - Custom restic URI (leave blank to build from the fields below) **ADVANCED**
CFG_BACKUP_LOC_1_SSH_USER= # SSH User - For sftp type CFG_BACKUP_LOC_1_SSH_USER= # SSH User - For sftp type
CFG_BACKUP_LOC_1_SSH_HOST= # SSH Host - For sftp type CFG_BACKUP_LOC_1_SSH_HOST= # SSH Host - For sftp type
CFG_BACKUP_LOC_1_SSH_PORT=22 # SSH Port - For sftp type CFG_BACKUP_LOC_1_SSH_PORT=22 # SSH Port - For sftp type **ADVANCED**
CFG_BACKUP_LOC_1_SSH_PATH= # SSH Remote Path - Path on the remote host where the repo lives CFG_BACKUP_LOC_1_SSH_PATH= # SSH Remote Path - Path on the remote host where the repo lives
CFG_BACKUP_LOC_1_SSH_AUTH=key # SSH Authentication - [key:SSH key (~/.ssh/id_rsa)|password:Password (via sshpass)] CFG_BACKUP_LOC_1_SSH_AUTH=key # SSH Authentication - [key:SSH key (~/.ssh/id_rsa)|password:Password (via sshpass)]
CFG_BACKUP_LOC_1_SSH_PASS= # SSH Password - Used only when SSH Authentication is set to Password CFG_BACKUP_LOC_1_SSH_PASS= # SSH Password - Used only when SSH Authentication is set to Password
@ -18,7 +18,7 @@ CFG_BACKUP_LOC_1_S3_ACCESS_KEY= # S3 Access Key
CFG_BACKUP_LOC_1_S3_SECRET_KEY= # S3 Secret Key - For s3 type CFG_BACKUP_LOC_1_S3_SECRET_KEY= # S3 Secret Key - For s3 type
CFG_BACKUP_LOC_1_B2_ACCOUNT_ID= # B2 Account ID - For b2 type CFG_BACKUP_LOC_1_B2_ACCOUNT_ID= # B2 Account ID - For b2 type
CFG_BACKUP_LOC_1_B2_ACCOUNT_KEY= # B2 Account Key - For b2 type CFG_BACKUP_LOC_1_B2_ACCOUNT_KEY= # B2 Account Key - For b2 type
CFG_BACKUP_LOC_1_APPEND_ONLY=false # Append-only - Refuse forget/prune for this location (ransomware-safe) CFG_BACKUP_LOC_1_APPEND_ONLY=false # Append-only - Refuse forget/prune for this location (ransomware-safe) **ADVANCED**
CFG_BACKUP_LOC_1_CUSTOM_RETENTION=false # Custom Retention - Override the global retention for this location CFG_BACKUP_LOC_1_CUSTOM_RETENTION=false # Custom Retention - Override the global retention for this location
CFG_BACKUP_LOC_1_KEEP_LAST= # Keep Last - Snapshots to always retain (blank = global) CFG_BACKUP_LOC_1_KEEP_LAST= # Keep Last - Snapshots to always retain (blank = global)
CFG_BACKUP_LOC_1_KEEP_DAILY= # Keep Daily - Days (blank = global) CFG_BACKUP_LOC_1_KEEP_DAILY= # Keep Daily - Days (blank = global)

View File

@ -37,10 +37,10 @@ locationAdd()
echo "CFG_BACKUP_LOC_${idx}_TYPE=${type} # Type - Backend [local:Local / mounted path|sftp:SFTP|rest:REST|s3:S3|b2:Backblaze B2|gs:Google Cloud Storage|azure:Azure|rclone:rclone]" echo "CFG_BACKUP_LOC_${idx}_TYPE=${type} # Type - Backend [local:Local / mounted path|sftp:SFTP|rest:REST|s3:S3|b2:Backblaze B2|gs:Google Cloud Storage|azure:Azure|rclone:rclone]"
echo "CFG_BACKUP_LOC_${idx}_PATH_MODE=${default_path_mode} # Path Mode - Where this location stores its data [auto:Automatic (/docker/backups/<id>)|custom:Custom path]" echo "CFG_BACKUP_LOC_${idx}_PATH_MODE=${default_path_mode} # Path Mode - Where this location stores its data [auto:Automatic (/docker/backups/<id>)|custom:Custom path]"
echo "CFG_BACKUP_LOC_${idx}_PATH=${default_path} # Custom Path - Filesystem path on this server (used when Path Mode = Custom)" echo "CFG_BACKUP_LOC_${idx}_PATH=${default_path} # Custom Path - Filesystem path on this server (used when Path Mode = Custom)"
echo "CFG_BACKUP_LOC_${idx}_URI= # URI Override - Custom restic URI (leave blank to build from the fields below)" echo "CFG_BACKUP_LOC_${idx}_URI= # URI Override - Custom restic URI (leave blank to build from the fields below) **ADVANCED**"
echo "CFG_BACKUP_LOC_${idx}_SSH_USER= # SSH User - For sftp type" echo "CFG_BACKUP_LOC_${idx}_SSH_USER= # SSH User - For sftp type"
echo "CFG_BACKUP_LOC_${idx}_SSH_HOST= # SSH Host - For sftp type" echo "CFG_BACKUP_LOC_${idx}_SSH_HOST= # SSH Host - For sftp type"
echo "CFG_BACKUP_LOC_${idx}_SSH_PORT=22 # SSH Port - For sftp type" echo "CFG_BACKUP_LOC_${idx}_SSH_PORT=22 # SSH Port - For sftp type **ADVANCED**"
echo "CFG_BACKUP_LOC_${idx}_SSH_PATH= # SSH Remote Path - Path on the remote host where the repo lives" echo "CFG_BACKUP_LOC_${idx}_SSH_PATH= # SSH Remote Path - Path on the remote host where the repo lives"
echo "CFG_BACKUP_LOC_${idx}_SSH_AUTH=key # SSH Authentication - [key:SSH key (~/.ssh/id_rsa)|password:Password (via sshpass)]" echo "CFG_BACKUP_LOC_${idx}_SSH_AUTH=key # SSH Authentication - [key:SSH key (~/.ssh/id_rsa)|password:Password (via sshpass)]"
echo "CFG_BACKUP_LOC_${idx}_SSH_PASS= # SSH Password - Used only when SSH Authentication is set to Password" echo "CFG_BACKUP_LOC_${idx}_SSH_PASS= # SSH Password - Used only when SSH Authentication is set to Password"
@ -48,7 +48,7 @@ locationAdd()
echo "CFG_BACKUP_LOC_${idx}_S3_SECRET_KEY=" echo "CFG_BACKUP_LOC_${idx}_S3_SECRET_KEY="
echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_ID=" echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_ID="
echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_KEY=" echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_KEY="
echo "CFG_BACKUP_LOC_${idx}_APPEND_ONLY=false" echo "CFG_BACKUP_LOC_${idx}_APPEND_ONLY=false # Append-only - Refuse forget/prune for this location (ransomware-safe) **ADVANCED**"
echo "CFG_BACKUP_LOC_${idx}_CUSTOM_RETENTION=false" echo "CFG_BACKUP_LOC_${idx}_CUSTOM_RETENTION=false"
echo "CFG_BACKUP_LOC_${idx}_KEEP_LAST=" echo "CFG_BACKUP_LOC_${idx}_KEEP_LAST="
echo "CFG_BACKUP_LOC_${idx}_KEEP_DAILY=" echo "CFG_BACKUP_LOC_${idx}_KEEP_DAILY="

View File

@ -285,6 +285,80 @@ EOF
done done
done done
# Per-location keys live in configs/backup/locations/<n>/location.config,
# which the flat-file loop above never descends into. Emit them here so the
# Locations editor renders from config metadata like every other page. A
# "**ADVANCED**" token anywhere in a field's comment marks it for the
# editor's "Advanced" reveal (stripped from the user-facing description).
local loc_cfg loc_advanced
for loc_cfg in "$configs_dir"/backup/locations/*/location.config; do
[[ -f "$loc_cfg" ]] || continue
while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
[[ "$line" =~ ^CFG_BACKUP_LOC_[0-9]+_[A-Z0-9_]+= ]] || continue
var_name="${line%%=*}"
rest="${line#*=}"
if [[ "$rest" == *#* ]]; then
var_value="${rest%%#*}"
comment="${rest#*#}"
else
var_value="$rest"
comment=""
fi
var_value="${var_value//$'\r'/}"
var_value="${var_value%"${var_value##*[![:space:]]}"}"
loc_advanced="false"
title=""
description=""
splitOptions=""
if [[ -n "$comment" ]]; then
comment="${comment#"${comment%%[![:space:]]*}"}"
if [[ "$comment" == *'**ADVANCED**'* ]]; then
loc_advanced="true"
comment="${comment//\*\*ADVANCED\*\*/}"
comment="${comment%"${comment##*[![:space:]]}"}"
fi
splitTitleDesc "$comment"
title="$splitTitle"
description="$splitDesc"
fi
if [[ "$var_value" =~ ^\"(.*)\"$ ]]; then
var_value="${BASH_REMATCH[1]}"
fi
var_value=$(jsonEscape "$var_value")
title=$(jsonEscape "$title")
description=$(jsonEscape "$description")
if [[ $first_config == true ]]; then
first_config=false
printf ' "%s": {\n' "$var_name" >> "$temp_file"
else
printf ' ,"%s": {\n' "$var_name" >> "$temp_file"
fi
printf ' "value": "%s",\n' "$var_value" >> "$temp_file"
printf ' "category": "backup",\n' >> "$temp_file"
printf ' "subcategory": "backup_locations",\n' >> "$temp_file"
printf ' "advanced": %s' "$loc_advanced" >> "$temp_file"
if [[ -n "$title" || -n "$description" || -n "$splitOptions" ]]; then
printf ',\n' >> "$temp_file"
else
printf '\n' >> "$temp_file"
fi
[[ -n "$title" ]] && printf ' "title": "%s",\n' "$title" >> "$temp_file"
[[ -n "$description" ]] && printf ' "description": "%s"' "$description" >> "$temp_file"
if [[ -n "$splitOptions" ]]; then
[[ -n "$description" ]] && printf ',\n' >> "$temp_file"
printf ' "options": %s\n' "$splitOptions" >> "$temp_file"
elif [[ -n "$description" ]]; then
printf '\n' >> "$temp_file"
fi
printf ' }\n' >> "$temp_file"
done < "$loc_cfg"
done
cat >> "$temp_file" << 'EOF' cat >> "$temp_file" << 'EOF'
} }