From 17de0a5a77fa63e2bee396c2f4ea50ed344e7d78 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Fri, 3 Jul 2026 21:27:33 +0200 Subject: [PATCH] Update 1.2.2.2 beta --- scripts/backup_restore/backup_host.sh | 11 +++- .../collectors/collect_source_host.sh | 10 +--- .../backup_restore/lib_host_backup_common.sh | 53 ++++++++++++++----- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/scripts/backup_restore/backup_host.sh b/scripts/backup_restore/backup_host.sh index 1b829076..2eb61d26 100755 --- a/scripts/backup_restore/backup_host.sh +++ b/scripts/backup_restore/backup_host.sh @@ -149,12 +149,19 @@ _bk_pbs() { "${cmd[@]}" 2>&1 | tee -a "$log_file"; then # Main backup OK — also upload the keyfile recovery blob if - # one was configured. This runs as a SEPARATE backup group + # one was configured AND this backup actually used the + # keyfile. Gating on HB_PBS_KEYFILE_OPT (rather than only on + # the file existing on disk) stops the upload when the + # operator declined encryption for this run but a recovery + # blob is still cached from a prior encrypted backup: in + # that case the blob does not describe this snapshot and + # uploading it as a paired recovery would be misleading. + # This runs as a SEPARATE backup group # (`host/proxmenux-keyrecovery-`) with NO --keyfile, # so PBS stores it as a plain (non-PBS-encrypted) blob that # can be retrieved during fresh-install recovery. The blob # is still passphrase-protected by openssl. - if [[ -f "$HB_STATE_DIR/pbs-key.recovery.enc" ]]; then + if [[ -n "$HB_PBS_KEYFILE_OPT" && -f "$HB_STATE_DIR/pbs-key.recovery.enc" ]]; then hb_pbs_upload_recovery_blob "$epoch" \ || msg_warn "$(translate "Recovery blob upload failed — main backup is OK, but keyfile recovery from PBS will not be available for this snapshot.")" fi diff --git a/scripts/backup_restore/collectors/collect_source_host.sh b/scripts/backup_restore/collectors/collect_source_host.sh index e105a9b5..67a475a4 100755 --- a/scripts/backup_restore/collectors/collect_source_host.sh +++ b/scripts/backup_restore/collectors/collect_source_host.sh @@ -61,12 +61,6 @@ esac # ── memory_kb ── memory_kb="$(awk '/^MemTotal:/{print $2; exit}' /proc/meminfo 2>/dev/null || echo 0)" -# ── subscription_status ── -subscription_status="" -if command -v pvesubscription >/dev/null 2>&1; then - subscription_status="$(pvesubscription get 2>/dev/null | awk -F: '/^status:/{sub(/^[ \t]+/,"",$2); print $2; exit}')" -fi - # Build JSON. Use --arg for strings (always quoted), --argjson for # numbers/arrays/null. Empty strings → null per schema convention. jq -n \ @@ -81,7 +75,6 @@ jq -n \ --arg cpu_model "$cpu_model" \ --arg cpu_arch "$cpu_arch" \ --argjson memory_kb "$memory_kb" \ - --arg subscription_status "$subscription_status" \ '{ hostname: $hostname, pve_version: (if $pve_version == "" then null else $pve_version end), @@ -93,6 +86,5 @@ jq -n \ root_fs: $root_fs, cpu_model: $cpu_model, cpu_arch: $cpu_arch, - memory_kb: $memory_kb, - subscription_status: (if $subscription_status == "" then null else $subscription_status end) + memory_kb: $memory_kb }' diff --git a/scripts/backup_restore/lib_host_backup_common.sh b/scripts/backup_restore/lib_host_backup_common.sh index 0d88eec6..06b997ee 100755 --- a/scripts/backup_restore/lib_host_backup_common.sh +++ b/scripts/backup_restore/lib_host_backup_common.sh @@ -869,10 +869,17 @@ hb_select_pbs_repository() { # passphrase. Encrypt the keyfile with openssl using that # passphrase → produces `pbs-key.recovery.enc`. # 2. On every PBS backup, we upload `pbs-key.recovery.enc` to a -# SEPARATE backup group (`host/proxmenux-keyrecovery-`) +# SEPARATE backup group (`host/hostcfg--keyrecovery`) # with NO `--keyfile` flag — so PBS stores it as a regular # (non-PBS-encrypted) blob. The blob is still protected by -# the operator's passphrase via openssl. +# the operator's passphrase via openssl. The `-keyrecovery` +# suffix on the same `hostcfg-` prefix keeps the two +# groups adjacent in the PBS UI, making the recovery snapshots +# recognisable as belonging to this host's backups instead of +# looking like an unrelated group that an operator might delete +# by mistake. Legacy builds used the ID `proxmenux-keyrecovery-`; +# the recovery discovery below matches both patterns so old +# escrow blobs are still usable. # 3. On a fresh install where the local keyfile is missing, the # restore flow looks up the recovery group in PBS, downloads # the blob, asks for the passphrase, decrypts it, and writes @@ -977,7 +984,7 @@ hb_pbs_upload_recovery_blob() { "keyrecovery.conf:$recovery_enc" \ --repository "$HB_PBS_REPOSITORY" \ --backup-type host \ - --backup-id "proxmenux-keyrecovery-$(hostname)" \ + --backup-id "hostcfg-$(hostname)-keyrecovery" \ --backup-time "$epoch" \ >/dev/null 2>&1 } @@ -992,8 +999,12 @@ hb_pbs_try_keyfile_recovery() { return 1 # silently — main path will surface a clearer error fi - # Discover all proxmenux-keyrecovery-* groups in PBS, picking - # the newest snapshot for each group (one row per host). + # Discover keyrecovery groups in PBS. Two patterns are matched: + # - hostcfg--keyrecovery (current naming — groups + # adjacent to the main hostcfg-) + # - proxmenux-keyrecovery- (legacy naming — pre-1.2.2.2) + # Both are surfaced together so existing escrow blobs from older + # builds remain usable during a fresh-install recovery. local -a recovery_entries=() mapfile -t recovery_entries < <( PBS_PASSWORD="$HB_PBS_SECRET" \ @@ -1001,7 +1012,12 @@ hb_pbs_try_keyfile_recovery() { proxmox-backup-client snapshot list \ --repository "$HB_PBS_REPOSITORY" \ --output-format json 2>/dev/null \ - | jq -r '.[] | select(."backup-type" == "host" and (."backup-id" | startswith("proxmenux-keyrecovery-"))) | "\(."backup-id")|\(."backup-time")"' 2>/dev/null \ + | jq -r '.[] + | select(."backup-type" == "host" + and ( ((."backup-id" | startswith("hostcfg-")) and (."backup-id" | endswith("-keyrecovery"))) + or (."backup-id" | startswith("proxmenux-keyrecovery-")) + )) + | "\(."backup-id")|\(."backup-time")"' 2>/dev/null \ | sort -t'|' -k1,1 -k2,2nr \ | awk -F'|' '!seen[$1]++' ) @@ -1020,7 +1036,14 @@ hb_pbs_try_keyfile_recovery() { local entry id_part host_part iso_label for entry in "${recovery_entries[@]}"; do id_part="${entry%%|*}" - host_part="${id_part#proxmenux-keyrecovery-}" + # Strip either naming convention to surface just the + # source hostname in the menu label. + if [[ "$id_part" == hostcfg-*-keyrecovery ]]; then + host_part="${id_part#hostcfg-}" + host_part="${host_part%-keyrecovery}" + else + host_part="${id_part#proxmenux-keyrecovery-}" + fi iso_label=$(date -u -d "@${entry##*|}" '+%Y-%m-%d %H:%M' 2>/dev/null || echo "${entry##*|}") menu+=("$i" "$host_part — $iso_label UTC") ((i++)) @@ -1171,17 +1194,23 @@ hb_ask_pbs_encryption() { # from a clean state instead of picking up an unusable # "existing keyfile". [[ -f "$key_file" && ! -s "$key_file" ]] && rm -f "$key_file" 2>/dev/null - # Surface the actual error from proxmox-backup-client to the - # operator — silent failures here were the reason the user - # kept seeing `Encryption: Disabled` after entering the - # passphrase. Now we show what proxmox-backup-client said. + # Surface the actual error from proxmox-backup-client and + # abort the backup: the operator asked for encryption, so + # silently downgrading to unencrypted (past behaviour) hid + # the failure behind a modal that a hurried operator would + # dismiss without reading. Returning 1 propagates cancel to + # _bk_pbs, which drops back to the previous menu so the + # underlying issue (perms, disk full, ...) can be fixed + # before retrying. local err_msg - err_msg="$(hb_translate "Failed to create encryption key. Backup will proceed without encryption.")"$'\n\n' + err_msg="$(hb_translate "Failed to create encryption key. Backup cancelled — fix the underlying issue and retry.")"$'\n\n' err_msg+="$(hb_translate "Tool exit code:") $create_rc"$'\n' err_msg+="$(hb_translate "Tool output:")"$'\n' err_msg+="${create_stderr:-(empty)}" dialog --backtitle "ProxMenux" --title "$(hb_translate "Encryption key creation failed")" \ --msgbox "$err_msg" 14 78 + HB_PBS_KEYFILE_OPT="" + return 1 fi }