feat: backup test script, ntfy notifications, and error categorization

extras/test_backup.sh — new unified test script (Kopia + Borg):
  • Stops container, moves live data aside, restores latest backup,
    compares restored vs live with diff -rq (content, not timestamps),
    moves live data back and restarts container
  • PASS = restore succeeded; diff output is informational (files changed
    since last backup are normal)
  • FAIL = restore command failed or target empty after restore
  • --list flag, CLI service arg, interactive picker
  • Handles both full-service dirs and sub-path sources (gaming-backup)
  • Cleanup trap always restores live data even on error
  • Sends ntfy notification on pass and fail

extras/backup_kopia.sh, backup_borg.sh, backup_gaming.sh:
  • ntfy_send() + categorize_error() helpers added
  • Each snapshot/archive failure captures stderr and categorizes:
    disk full, remote unreachable, repository not found, wrong passphrase,
    permission denied, unknown error
  • Single ntfy notification at end: success (low priority) or failure
    (urgent) with per-service failure reasons listed
  • backup_borg.sh: changed 2>&1 | pipe to 2>"$_ERR" | so stdout logs
    cleanly and stderr is captured for error categorization

services/backup.sh, borg-backup.sh, gaming-backup.sh:
  • New ntfy prompt section in installer (URL + optional token)
  • NTFY_URL / NTFY_TOKEN written to backup.conf
  • test_backup.sh copied from extras/ into service dir
  • Summary updated to show test_backup.sh commands and ntfy URL

https://claude.ai/code/session_019XgsQ13XKm4Zj3cNsDNwHj
This commit is contained in:
Claude
2026-06-04 20:03:30 +00:00
parent 925ded308f
commit 862ecf10e9
7 changed files with 627 additions and 20 deletions
+40 -2
View File
@@ -246,7 +246,21 @@ install_backup() {
prompt_text " Snapshots to keep (latest)? [7]:" "7" KEEP_LATEST
KEEP_LATEST="${KEEP_LATEST:-7}"
# ── 7. Create dirs + init Kopia repos ────────────────────────────────────
# ── Notifications (ntfy) ─────────────────────────────────────────────────
echo ""
echo "═══════════════════════════════════════════════════════"
echo " NOTIFICATIONS (optional)"
echo "═══════════════════════════════════════════════════════"
echo ""
echo " Receive a push notification after every backup (and on failures)."
echo " Uses ntfy — free and self-hostable. Create a topic at https://ntfy.sh"
echo " Example URL: https://ntfy.sh/my-backup-alerts"
echo ""
local NTFY_URL="" NTFY_TOKEN=""
prompt_text " ntfy topic URL (blank to skip):" "" NTFY_URL
if [ -n "$NTFY_URL" ]; then
prompt_text " ntfy access token (blank if public/no auth):" "" NTFY_TOKEN
fi
mkdir -p "$DIR"
ensure_docker_dir_ownership "$DIR"
@@ -320,6 +334,12 @@ install_backup() {
echo "# Example SFTP: REMOTE_TYPE=sftp REMOTE_ARGS=\"--host H --username U --path /srv/...\""
echo "REMOTE_TYPE=\"none\""
echo "REMOTE_ARGS=\"\""
echo ""
echo "# ── Notifications (ntfy) ─────────────────────────────────────────────────────"
echo "# Set NTFY_URL to receive backup success/failure alerts."
echo "# Leave blank to disable. NTFY_TOKEN is optional (for private topics)."
printf "NTFY_URL='%s'\n" "${NTFY_URL:-}"
printf "NTFY_TOKEN='%s'\n" "${NTFY_TOKEN:-}"
} > "$CONF_FILE"
chown root:root "$CONF_FILE" 2>/dev/null || true
chmod 600 "$CONF_FILE"
@@ -344,7 +364,19 @@ install_backup() {
log_warning "Copy it manually: cp extras/restore_kopia.sh $RESTORE"
fi
# ── 11. Systemd timer ────────────────────────────────────────────────────
# ── 11. Install test script ──────────────────────────────────────────────
local TEST_SCRIPT="$DIR/test_backup.sh"
local TEST_SRC="${HERE:-}/extras/test_backup.sh"
if [ -f "$TEST_SRC" ]; then
cp "$TEST_SRC" "$TEST_SCRIPT"
chmod +x "$TEST_SCRIPT"
chown root:root "$TEST_SCRIPT" 2>/dev/null || true
log_success "test_backup.sh installed"
else
log_warning "extras/test_backup.sh not found — test script not installed"
fi
# ── 12. Systemd timer ────────────────────────────────────────────────────
log_info "Installing systemd timer ($SCHED_LABEL)..."
local AUTORUN=""
if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
@@ -427,6 +459,12 @@ SVCEOF
echo " sudo $RESTORE"
echo " sudo $RESTORE --list"
echo ""
echo " Backup test (stop/restore/compare/restore-back):"
echo " sudo $TEST_SCRIPT test most recent backup"
echo " sudo $TEST_SCRIPT --list list testable services"
echo " sudo $TEST_SCRIPT <service> test a specific service"
[ -n "${NTFY_URL:-}" ] && echo "" && echo " Notifications: $NTFY_URL"
echo ""
[ -n "$AUTORUN" ] && echo " $AUTORUN" && echo ""
log_warning "Save your passwords (in backup.conf) somewhere safe —"
log_warning "without them the encrypted repos cannot be restored."
+41 -1
View File
@@ -191,6 +191,22 @@ install_borg_backup() {
KEEP_WEEKLY="${KEEP_WEEKLY:-4}"
KEEP_MONTHLY="${KEEP_MONTHLY:-3}"
# ── Notifications (ntfy) ─────────────────────────────────────────────────
echo ""
echo "═══════════════════════════════════════════════════════"
echo " NOTIFICATIONS (optional)"
echo "═══════════════════════════════════════════════════════"
echo ""
echo " Receive a push notification after every backup (and on failures)."
echo " Uses ntfy — free and self-hostable. Create a topic at https://ntfy.sh"
echo " Example URL: https://ntfy.sh/my-backup-alerts"
echo ""
local NTFY_URL="" NTFY_TOKEN=""
prompt_text " ntfy topic URL (blank to skip):" "" NTFY_URL
if [ -n "$NTFY_URL" ]; then
prompt_text " ntfy access token (blank if public/no auth):" "" NTFY_TOKEN
fi
# ── 7. Create dirs + init Borg repos ─────────────────────────────────────
mkdir -p "$DIR"
ensure_docker_dir_ownership "$DIR"
@@ -262,6 +278,12 @@ install_borg_backup() {
echo "# SVC_${svc_var}=\"default\""
fi
done
echo ""
echo "# ── Notifications (ntfy) ─────────────────────────────────────────────────────"
echo "# Set NTFY_URL to receive backup success/failure alerts."
echo "# Leave blank to disable. NTFY_TOKEN is optional (for private topics)."
printf "NTFY_URL='%s'\n" "${NTFY_URL:-}"
printf "NTFY_TOKEN='%s'\n" "${NTFY_TOKEN:-}"
} > "$CONF_FILE"
chown root:root "$CONF_FILE" 2>/dev/null || true
chmod 600 "$CONF_FILE"
@@ -286,7 +308,19 @@ install_borg_backup() {
log_warning "Copy it manually: cp extras/restore_borg.sh $RESTORE"
fi
# ── 11. Systemd timer ─────────────────────────────────────────────────────
# ── 11. Install test script ──────────────────────────────────────────────
local TEST_SCRIPT="$DIR/test_backup.sh"
local TEST_SRC="${HERE:-}/extras/test_backup.sh"
if [ -f "$TEST_SRC" ]; then
cp "$TEST_SRC" "$TEST_SCRIPT"
chmod +x "$TEST_SCRIPT"
chown root:root "$TEST_SCRIPT" 2>/dev/null || true
log_success "test_backup.sh installed"
else
log_warning "extras/test_backup.sh not found — test script not installed"
fi
# ── 12. Systemd timer ─────────────────────────────────────────────────────
log_info "Installing systemd timer ($SCHED_LABEL)..."
if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
tee "/etc/systemd/system/${SVC_NAME}.service" >/dev/null << SVCEOF
@@ -368,6 +402,12 @@ SVCEOF
echo " sudo $RESTORE"
echo " sudo $RESTORE --list"
echo ""
echo " Backup test (stop/restore/compare/restore-back):"
echo " sudo $TEST_SCRIPT test most recent backup"
echo " sudo $TEST_SCRIPT --list list testable services"
echo " sudo $TEST_SCRIPT <service> test a specific service"
[ -n "${NTFY_URL:-}" ] && echo "" && echo " Notifications: $NTFY_URL"
echo ""
log_warning "IMPORTANT — back up your Borg key and passphrase now."
echo " The key is stored in the repo itself (repokey-blake2 encryption)."
echo " Export it to a safe location:"
+40
View File
@@ -192,6 +192,21 @@ install_gaming_backup() {
prompt_text " How many recent snapshots to keep (latest)? [24]:" "24" KEEP_LATEST
local KEEP_DAILY=7 KEEP_WEEKLY=4 KEEP_MONTHLY=6
# ── Notifications (ntfy) ─────────────────────────────────────────────────
echo ""
echo "═══════════════════════════════════════════════════════"
echo " NOTIFICATIONS (optional)"
echo "═══════════════════════════════════════════════════════"
echo ""
echo " Receive a push notification after every backup (and on failures)."
echo " Uses ntfy — free and self-hostable. Create a topic at https://ntfy.sh"
echo ""
local NTFY_URL="" NTFY_TOKEN=""
prompt_text " ntfy topic URL (blank to skip):" "" NTFY_URL
if [ -n "$NTFY_URL" ]; then
prompt_text " ntfy access token (blank if public/no auth):" "" NTFY_TOKEN
fi
# ── 5. Write backup.conf ──────────────────────────────────────────────────
log_info "Writing $CONF_FILE ..."
tee "$CONF_FILE" >/dev/null << CONFEOF
@@ -226,6 +241,12 @@ BACKUP_WOLF="$BACKUP_WOLF" # /etc/wolf — config + profile_data
#
REMOTE_TYPE="none"
REMOTE_ARGS=""
# ── Notifications (ntfy) ─────────────────────────────────────────────────────
# Set NTFY_URL to receive backup success/failure alerts.
# Leave blank to disable. NTFY_TOKEN is optional (for private topics).
NTFY_URL="$NTFY_URL"
NTFY_TOKEN="$NTFY_TOKEN"
CONFEOF
chown root:root "$CONF_FILE" 2>/dev/null || true
chmod 600 "$CONF_FILE"
@@ -292,6 +313,18 @@ CONFEOF
log_warning "extras/restore_kopia.sh not found — restore script not installed"
fi
# ── Install test script ───────────────────────────────────────────────────
local TEST_SCRIPT="$BACKUP_DIR/test_backup.sh"
local TEST_SRC="${HERE:-}/extras/test_backup.sh"
if [ -f "$TEST_SRC" ]; then
cp "$TEST_SRC" "$TEST_SCRIPT"
chmod +x "$TEST_SCRIPT"
chown root:root "$TEST_SCRIPT" 2>/dev/null || true
log_success "test_backup.sh installed"
else
log_warning "extras/test_backup.sh not found — test script not installed"
fi
# ── 8. Install systemd timer (fallback: cron) ────────────────────────────
local AUTORUN=""
if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
@@ -369,6 +402,13 @@ UNITEOF
echo " sudo $WORKER snapshots list snapshots"
echo " sudo $RESTORE_DEST interactive restore"
echo " sudo $RESTORE_DEST --list list all snapshot sources"
echo ""
echo " Backup test (restore latest, compare, restore-back):"
echo " sudo $TEST_SCRIPT test most recent backup"
echo " sudo $TEST_SCRIPT --list list testable sources"
echo " sudo $TEST_SCRIPT <source> test a specific source"
[ -n "${NTFY_URL:-}" ] && echo "" && echo " Notifications: $NTFY_URL"
echo ""
echo " $AUTORUN"
echo ""
echo " Tip: also install the 'backup' service for nightly full-service recovery."