#!/usr/bin/env bash # restic backup: Synology SFTP (when reachable) + Backblaze B2 (always) set -euo pipefail source "$HOME/.credentials" LOG_DIR="$HOME/.local/log/restic" mkdir -p "$LOG_DIR" LOG="$LOG_DIR/$(date +%Y-%m-%d).log" EXCLUDES=( --exclude-file="$HOME/.config/restic/excludes" --exclude-caches ) run_backup() { local repo="$1" local label="$2" echo "--- $label backup ---" | tee -a "$LOG" restic -r "$repo" backup ~ "${EXCLUDES[@]}" \ --one-file-system \ --tag "$(hostname)" 2>&1 | tee -a "$LOG" restic -r "$repo" forget \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ --prune 2>&1 | tee -a "$LOG" } run_and_notify() { local repo="$1" local label="$2" local machine="$3" local destination="$4" set +e run_backup "$repo" "$label" local exit_code=$? set -e local status="failure" [[ $exit_code -eq 0 ]] && status="success" local snap snap=$(grep -oE 'snapshot [a-f0-9]+' "$LOG" 2>/dev/null | tail -1 | awk '{print $2}') notify_backup.rb \ --machine "$machine" \ --destination "$destination" \ --status "$status" \ ${snap:+--snapshot "$snap"} \ --log-path "$LOG" \ --notes "$(tail -10 "$LOG")" || true return $exit_code } echo "=== Backup started $(date) ===" | tee -a "$LOG" # Synology: attempt only if reachable (SSH key auth, 30s timeout for HDD spin-up) if ssh -o ConnectTimeout=30 -o BatchMode=yes synology 'ls /volume1/backup > /dev/null 2>&1' 2>/dev/null; then run_and_notify "sftp:${SYNOLOGY_HOST}:${SYNOLOGY_PATH}" "Synology" "desktop" "synology" else echo "Synology unreachable — skipping SFTP backup" | tee -a "$LOG" notify_backup.rb \ --machine desktop \ --destination synology \ --status skipped \ --log-path "$LOG" \ --notes "Synology unreachable at $(date)" || true fi # B2: clear any stale lock before attempting (safe no-op if no lock exists) restic -r "b2:${B2_BUCKET}:" unlock 2>&1 | tee -a "$LOG" || true run_and_notify "b2:${B2_BUCKET}:" "Backblaze B2" "desktop" "backblaze-b2" echo "=== Backup complete $(date) ===" | tee -a "$LOG"