#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="${REPO_ROOT:-$(cd "$SCRIPT_DIR/../../.." && pwd)}" POSTURE_CHECK="${POSTURE_CHECK:-$REPO_ROOT/services/posture-check/posture-check.sh}" FRESHNESS_CHECK="${FRESHNESS_CHECK:-$REPO_ROOT/ops/restore-tests/check-restore-freshness.sh}" PRE_BACKUP_DUMPS="${PRE_BACKUP_DUMPS:-$SCRIPT_DIR/pre-backup-dumps.sh}" NTFY_SCRIPT="${NTFY_SCRIPT:-$REPO_ROOT/ops/restore-tests/send-ntfy.sh}" NTFY_TOPIC="${NTFY_TOPIC:-homelab-alerts}" ALLOW_POSTURE_WARNING="${ALLOW_POSTURE_WARNING:-1}" case "${DUMP_ROOT:-}" in */latest) FRESHNESS_DUMP_ROOT="${FRESHNESS_DUMP_ROOT:-$DUMP_ROOT}" ;; "") FRESHNESS_DUMP_ROOT="${FRESHNESS_DUMP_ROOT:-/mnt/user/backups/borg/dumps/latest}" ;; *) FRESHNESS_DUMP_ROOT="${FRESHNESS_DUMP_ROOT:-$DUMP_ROOT/latest}" ;; esac # Externer Dead-Man's-Switch (endpoint-agnostisch: Healthchecks.io-Cloud oder # self-hosted). ntfy meldet nur Fehler eines tatsaechlich gestarteten Laufs; # der externe Switch faengt zusaetzlich den Fall ab, dass der Pre-Hook gar nicht # laeuft. Die Ping-URL ist eine Capability-URL -> wie ein Secret behandeln, # niemals ins Repo. Ist keine URL gesetzt, ist der Switch ein No-Op. HEALTHCHECKS_URL="${HEALTHCHECKS_URL:-${HEALTHCHECKS_BORG_URL:-}}" HEALTHCHECKS_URL_FILE="${HEALTHCHECKS_URL_FILE:-/mnt/user/appdata/secrets/healthchecks_borg_url}" if [ -z "$HEALTHCHECKS_URL" ] && [ -r "$HEALTHCHECKS_URL_FILE" ]; then HEALTHCHECKS_URL="$(tr -d '[:space:]' < "$HEALTHCHECKS_URL_FILE")" fi hc_ping() { # $1: optionaler Suffix ("/start" | "/fail"); leer = Erfolg [ -n "$HEALTHCHECKS_URL" ] || return 0 command -v curl >/dev/null 2>&1 || return 0 curl -fsS -m 10 --retry 3 "${HEALTHCHECKS_URL}${1:-}" >/dev/null 2>&1 || true } notify_failure() { local step="$1" local message="$2" if [ -x "$NTFY_SCRIPT" ]; then "$NTFY_SCRIPT" "$NTFY_TOPIC" "Borg pre-hook failed: $step" "$message" high || true fi hc_ping "/fail" } run_step() { local step="$1" shift echo "[pre-borg] Running $step" if "$@"; then echo "[pre-borg] OK: $step" else rc=$? notify_failure "$step" "Command failed with exit code $rc: $*" exit "$rc" fi } hc_ping "/start" echo "[pre-borg] Running posture-check" if "$POSTURE_CHECK"; then echo "[pre-borg] OK: posture-check" else rc=$? if [ "$rc" -eq 1 ] && [ "$ALLOW_POSTURE_WARNING" = "1" ]; then echo "[pre-borg] WARNING: posture-check returned warnings; continuing because ALLOW_POSTURE_WARNING=1" else notify_failure "posture-check" "Command failed with exit code $rc: $POSTURE_CHECK" exit "$rc" fi fi run_step "pre-backup-dumps" "$PRE_BACKUP_DUMPS" run_step "restore-freshness" env DUMP_ROOT="$FRESHNESS_DUMP_ROOT" "$FRESHNESS_CHECK" echo "[pre-borg] All pre-flight checks passed" hc_ping