Fix DR-spare path reset on reinstall and tilde-quoting in remote commands

Two stacked bugs, found together when re-running the backup installer to
add an SFTP mirror silently reverted a previously-set absolute
DR_SYNC_PATH back to the script's tilde-based default, which then failed
outright:

1. services/backup.sh never read DR_SYNC_HOST/DR_SYNC_PATH back from an
   existing backup.conf before prompting (every other setting in this file
   does — passwords, mirrors). Accepting the prompt defaults on a rerun
   silently reset both to blank/"~/docker/backup" instead of keeping what
   was already configured. Fixed by reading them back the same way
   DEST_*_PASSWORD already does.

2. extras/backup_kopia.sh's DR-spare sync wraps the remote path in single
   quotes for its `ssh host "mkdir -p '...'"` / `"chmod 600 '.../...'"`
   commands. Single-quoting a leading ~ stops the remote shell from
   expanding it at all, so it looked for a literal directory named "~"
   instead of the home directory — breaking the script's own DEFAULT
   DR_SYNC_PATH ("~/docker/backup") for anyone who actually used it.
   rsync's own transfer step has separate, correct tilde handling, which is
   why the sync itself "succeeded" while the follow-up chmod couldn't find
   the file. Fixed with a small _dr_remote_quote() helper that keeps a
   leading ~/ outside the quotes while still safely quoting the rest of
   the path.

Verified the quoting fix by parsing the exact constructed command string
in bash directly — a plain '~/docker/backup' stays literal (the bug),
~/'docker/backup' correctly expands to $HOME/docker/backup (the fix).
This commit is contained in:
Claude
2026-08-14 22:09:25 +00:00
parent 9edd821349
commit b9152369ef
2 changed files with 28 additions and 4 deletions
+6 -2
View File
@@ -563,9 +563,13 @@ install_backup() {
echo " up first if you haven't (ssh-keygen, then ssh-copy-id to the spare)."
echo ""
local DR_SYNC_HOST="" DR_SYNC_PATH=""
prompt_text " Spare box SSH destination, user@host (blank to skip):" "" DR_SYNC_HOST
if [ -f "$CONF_FILE" ]; then
DR_SYNC_HOST="$(grep '^DR_SYNC_HOST=' "$CONF_FILE" 2>/dev/null | sed -E "s/^DR_SYNC_HOST='(.*)'\$/\1/")"
DR_SYNC_PATH="$(grep '^DR_SYNC_PATH=' "$CONF_FILE" 2>/dev/null | sed -E "s/^DR_SYNC_PATH='(.*)'\$/\1/")"
fi
prompt_text " Spare box SSH destination, user@host (blank to skip):" "$DR_SYNC_HOST" DR_SYNC_HOST
if [ -n "$DR_SYNC_HOST" ]; then
prompt_text " Path for backup.conf/README on the spare:" "~/docker/backup" DR_SYNC_PATH
prompt_text " Path for backup.conf/README on the spare:" "${DR_SYNC_PATH:-~/docker/backup}" DR_SYNC_PATH
DR_SYNC_PATH="${DR_SYNC_PATH:-~/docker/backup}"
# Catch a missing/unauthorized key now, not at 2am during the first