74 lines
2.5 KiB
Bash
74 lines
2.5 KiB
Bash
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# restic-backup.sh — user-level backup script
|
|
# Deployed to: ~/.local/bin/restic-backup.sh
|
|
#
|
|
# Runs as a regular user — no sudo required.
|
|
# Config: ~/.config/restic/env and ~/.config/restic/excludes.txt
|
|
# ---------------------------------------------------------------------------
|
|
|
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
|
|
|
# Load environment — set -a auto-exports all variables to child processes
|
|
set -a && source "${XDG_CONFIG_HOME:-$HOME/.config}/restic/env" && set +a
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Server reachability check with retry
|
|
# ---------------------------------------------------------------------------
|
|
|
|
BACKUP_HOST="${BACKUP_SERVER%%:*}"
|
|
BACKUP_PORT="${BACKUP_SERVER##*:}"
|
|
MAX_RETRIES=3
|
|
RETRY_MIN=600 # 10 min
|
|
RETRY_MAX=1800 # 30 min
|
|
|
|
server_reachable() {
|
|
(echo >/dev/tcp/"${BACKUP_HOST}"/"${BACKUP_PORT}") 2>/dev/null
|
|
}
|
|
|
|
wait_for_server() {
|
|
local attempt=1
|
|
while ! server_reachable; do
|
|
if [ "$attempt" -ge "$MAX_RETRIES" ]; then
|
|
log "ERROR: Backup server ${BACKUP_SERVER} unreachable after ${MAX_RETRIES} attempts. Giving up."
|
|
exit 1
|
|
fi
|
|
local delay=$(( RANDOM % (RETRY_MAX - RETRY_MIN + 1) + RETRY_MIN ))
|
|
log "Backup server unreachable (attempt ${attempt}/${MAX_RETRIES}). Retrying in $(( delay / 60 )) min..."
|
|
sleep "$delay"
|
|
(( attempt++ ))
|
|
done
|
|
log "Backup server reachable."
|
|
}
|
|
|
|
log "=== Backup started on $(hostname) (${MACHINE_NAME}) as $(whoami) ==="
|
|
wait_for_server
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Backup
|
|
# ---------------------------------------------------------------------------
|
|
log "Running restic backup..."
|
|
|
|
# Word-split BACKUP_PATHS intentionally — each path is a separate argument
|
|
# shellcheck disable=SC2086
|
|
restic backup \
|
|
$BACKUP_PATHS \
|
|
--exclude-file "${XDG_CONFIG_HOME:-$HOME/.config}/restic/excludes.txt" \
|
|
--one-file-system \
|
|
--verbose
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Retention
|
|
# ---------------------------------------------------------------------------
|
|
log "Applying retention policy (daily=${KEEP_DAILY} weekly=${KEEP_WEEKLY} monthly=${KEEP_MONTHLY})..."
|
|
|
|
restic forget \
|
|
--keep-daily "${KEEP_DAILY}" \
|
|
--keep-weekly "${KEEP_WEEKLY}" \
|
|
--keep-monthly "${KEEP_MONTHLY}" \
|
|
--prune
|
|
|
|
log "=== Backup finished on $(hostname) (${MACHINE_NAME}) ==="
|