my-homelab-configs/scripts/backup-status

101 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
HOMELAB_STATE_DIR="${HOMELAB_STATE_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/homelab}"
GITEA_BACKUP_DIR="${LAB_GITEA_BACKUP_DIR:-/home/jv/backups/gitea}"
GITEA_DRILL_DIR="${GITEA_RESTORE_DRILL_DIR:-/home/jv/backups/gitea-restore-drills}"
TOFU_BACKUP_DIR="${HOMELAB_TOFU_STATE_BACKUP_DIR:-${HOMELAB_STATE_DIR}/tofu-state-backups}"
PIHOLE_CONFIG_FILES="${PIHOLE_CONFIG_FILES:-infra/rpi-services/adlists.txt infra/rpi-services/local-dns-records.txt infra/rpi-services/cname-records.txt infra/rpi-services/static-dhcp-hosts.txt}"
MAX_GITEA_AGE_HOURS="${LAB_BACKUP_MAX_GITEA_AGE_HOURS:-36}"
MAX_TOFU_AGE_HOURS="${LAB_BACKUP_MAX_TOFU_AGE_HOURS:-168}"
MAX_DRILL_AGE_HOURS="${LAB_BACKUP_MAX_DRILL_AGE_HOURS:-744}"
failures=0
warnings=0
section() {
printf '\n== %s ==\n' "$1"
}
latest_file() {
local dir="$1"
local pattern="$2"
if [ -d "$dir" ]; then
find "$dir" -maxdepth 1 -type f -name "$pattern" -printf '%T@ %p\n' 2>/dev/null |
sort -n |
tail -1 |
sed 's/^[^ ]* //'
fi
}
file_age_hours() {
local path="$1"
python3 - "$path" <<'PY'
import os
import sys
import time
path = sys.argv[1]
age = int((time.time() - os.path.getmtime(path)) / 3600)
print(age)
PY
}
check_latest() {
local label="$1"
local dir="$2"
local pattern="$3"
local max_age_hours="$4"
local severity="${5:-fail}"
local latest
local age_hours
latest="$(latest_file "$dir" "$pattern" || true)"
printf '%-30s ' "$label"
if [ -z "$latest" ]; then
printf '%s - missing in %s\n' "$severity" "$dir"
if [ "$severity" = "fail" ]; then
failures=$((failures + 1))
else
warnings=$((warnings + 1))
fi
return 0
fi
age_hours="$(file_age_hours "$latest")"
if [ "$age_hours" -le "$max_age_hours" ]; then
printf 'ok - age=%sh path=%s\n' "$age_hours" "$latest"
else
printf '%s - age=%sh max=%sh path=%s\n' "$severity" "$age_hours" "$max_age_hours" "$latest"
if [ "$severity" = "fail" ]; then
failures=$((failures + 1))
else
warnings=$((warnings + 1))
fi
fi
}
section "Backup Freshness"
check_latest "Gitea backup" "$GITEA_BACKUP_DIR" 'gitea-*.zip' "$MAX_GITEA_AGE_HOURS" fail
check_latest "OpenTofu state backup" "$TOFU_BACKUP_DIR" 'tofu-state-*.tgz' "$MAX_TOFU_AGE_HOURS" warn
check_latest "Restore drill report" "$GITEA_DRILL_DIR" 'restore-drill-*.txt' "$MAX_DRILL_AGE_HOURS" warn
section "Repo Managed Pi-hole Inputs"
for file in $PIHOLE_CONFIG_FILES; do
printf '%-30s ' "$file"
if [ -s "$file" ]; then
printf 'ok\n'
else
printf 'warn - missing or empty\n'
warnings=$((warnings + 1))
fi
done
section "Summary"
printf 'failures=%s warnings=%s\n' "$failures" "$warnings"
if [ "$failures" -gt 0 ]; then
exit 1
fi