Offer to actually set up VPN + SSH keys at the DR-spare prompt

Requested improvement: the disaster-recovery spare prompt in backup.sh
already ran a live connectivity check and, on failure, printed manual
instructions (set up wg-easy separately if the spare isn't reachable,
run ssh-keygen/ssh-copy-id yourself) — but never offered to do any of it
right there, even though every piece is safe to automate inline.

Now, when the passwordless SSH check fails:
- If wg-easy isn't installed yet, offers to chain-install it (guarded
  with declare -F install_wg-easy, same pattern asterisk.sh already uses
  for security-dashboard/pstn-trunk) — covers the common case where the
  spare is a home box with no port-forward and no path there at all yet,
  not just a missing key.
- If root has no SSH key, offers to generate one (ssh-keygen -t ed25519).
- Offers to run ssh-copy-id against the spare interactively right there
  — it prompts for the spare's login password itself, so this script
  never touches or sees that password, just invokes the real command
  inline instead of telling the operator to go run it themselves after.
- Re-runs the connectivity check after ssh-copy-id succeeds, so the
  install flow reports the actual current state instead of the
  pre-fix failure message.

Verified the has-a-key detection (the part most likely to have a subtle
&&/|| precedence bug) against all four cases — no key, only id_ed25519,
only id_rsa, both — behaves correctly in each.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn
This commit is contained in:
Claude
2026-08-14 02:03:59 +00:00
parent 90b0508e19
commit 8dd66945dd
+47 -2
View File
@@ -496,8 +496,53 @@ install_backup() {
log_success " SSH to $DR_SYNC_HOST works — spare sync will run after each backup."
else
log_warning " Couldn't SSH to $DR_SYNC_HOST without a password right now."
log_warning " Spare sync is saved but will fail until this works (as root, since"
log_warning " the backup timer runs as root): ssh-keygen; ssh-copy-id $DR_SYNC_HOST"
# If the spare isn't reachable at all (behind NAT, no port-forward —
# a home box is the common case), a passwordless key won't help
# until there's a network path there in the first place. Offer the
# VPN hub right here instead of just telling the user to go set
# one up separately and come back.
if [ ! -d "$DOCKER_DIR/wg-easy" ]; then
local _SETUP_VPN=""
prompt_yn " Spare box not directly reachable (behind NAT, no port-forward)? Set up a WireGuard VPN hub (wg-easy) now so they can reach each other? (y/n):" "n" _SETUP_VPN
if [[ "$_SETUP_VPN" =~ ^[Yy]$ ]]; then
if declare -F install_wg-easy >/dev/null 2>&1; then
install_wg-easy
else
log_warning " services/wg-easy.sh isn't loaded — run: sudo ./setup.sh wg-easy"
fi
fi
fi
local _HAVE_KEY=false
[ -f /root/.ssh/id_ed25519 ] || [ -f /root/.ssh/id_rsa ] && _HAVE_KEY=true
if [ "$_HAVE_KEY" = false ]; then
local _GEN_KEY=""
prompt_yn " No SSH key found for root — generate one now (ssh-keygen)? (y/n):" "y" _GEN_KEY
if [[ "$_GEN_KEY" =~ ^[Yy]$ ]]; then
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519 -q \
&& log_success " Generated /root/.ssh/id_ed25519" \
|| log_warning " ssh-keygen failed — generate one manually."
fi
fi
local _COPY_KEY=""
prompt_yn " Run ssh-copy-id to $DR_SYNC_HOST now? (asks for its login password interactively) (y/n):" "y" _COPY_KEY
if [[ "$_COPY_KEY" =~ ^[Yy]$ ]]; then
if ssh-copy-id "$DR_SYNC_HOST"; then
if ssh -o BatchMode=yes -o ConnectTimeout=5 "$DR_SYNC_HOST" true 2>/dev/null; then
log_success " SSH to $DR_SYNC_HOST now works — spare sync will run after each backup."
else
log_warning " ssh-copy-id reported success but the passwordless check still failed — check manually."
fi
else
log_warning " ssh-copy-id failed. Spare sync is saved but will fail until this works:"
log_warning " ssh-copy-id $DR_SYNC_HOST"
fi
else
log_warning " Spare sync is saved but will fail until this works (as root, since"
log_warning " the backup timer runs as root): ssh-copy-id $DR_SYNC_HOST"
fi
fi
fi