feat: verify scheduled backups
This commit is contained in:
+19
-1
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Creates a consistent SQLite backup through the running web container, then archives Hub uploads.
|
||||
# Optional: BACKUP_RETENTION_DAYS=30 BACKUP_OFFSITE_DIR=/mnt/backup/mebbling ./scripts/backup.sh
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$root_dir"
|
||||
stamp="$(date +%Y%m%d-%H%M%S)"
|
||||
@@ -15,4 +16,21 @@ docker compose exec -T -e BACKUP_PATH="/app/data/backups/$stamp/hub.db" web node
|
||||
'
|
||||
|
||||
tar -czf "$backup_dir/uploads.tar.gz" -C public uploads
|
||||
printf 'Created backup: %s\n' "$backup_dir"
|
||||
|
||||
docker compose exec -T -e BACKUP_PATH="/app/data/backups/$stamp/hub.db" web node -e '
|
||||
const Database = require("better-sqlite3"); const db = new Database(process.env.BACKUP_PATH, { readonly: true });
|
||||
const row = db.prepare("PRAGMA integrity_check").get(); db.close(); if (row.integrity_check !== "ok") { console.error("SQLite integrity check failed"); process.exit(1); }
|
||||
'
|
||||
tar -tzf "$backup_dir/uploads.tar.gz" >/dev/null
|
||||
(cd "$backup_dir" && sha256sum hub.db uploads.tar.gz > SHA256SUMS)
|
||||
|
||||
if [[ -n "${BACKUP_OFFSITE_DIR:-}" ]]; then
|
||||
destination="$BACKUP_OFFSITE_DIR/$stamp"; mkdir -p "$destination"
|
||||
cp -a "$backup_dir/." "$destination/"
|
||||
printf 'Copied verified backup to: %s\n' "$destination"
|
||||
fi
|
||||
if [[ -n "${BACKUP_RETENTION_DAYS:-}" ]]; then
|
||||
[[ "$BACKUP_RETENTION_DAYS" =~ ^[0-9]+$ ]] || { echo "BACKUP_RETENTION_DAYS must be a non-negative integer" >&2; exit 2; }
|
||||
find data/backups -mindepth 1 -maxdepth 1 -type d -mtime "+$BACKUP_RETENTION_DAYS" -exec rm -rf {} +
|
||||
fi
|
||||
printf 'Created and verified backup: %s\n' "$backup_dir"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Installs a daily 03:15 host cron job. Run from WSL after setting an offsite mount if desired.
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
line="15 3 * * * cd $root_dir && BACKUP_RETENTION_DAYS=30 ./scripts/backup.sh >> data/backup-cron.log 2>&1"
|
||||
(crontab -l 2>/dev/null | grep -Fv "scripts/backup.sh"; echo "$line") | crontab -
|
||||
printf 'Installed daily backup cron job. Inspect with: crontab -l\n'
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then echo "Usage: CONFIRM_RESTORE=YES ./scripts/restore.sh data/backups/YYYYMMDD-HHMMSS" >&2; exit 2; fi
|
||||
if [[ "${CONFIRM_RESTORE:-}" != "YES" ]]; then echo "Refusing restore. Set CONFIRM_RESTORE=YES after verifying the backup path." >&2; exit 2; fi
|
||||
backup_dir="$1"; [[ -f "$backup_dir/hub.db" && -f "$backup_dir/uploads.tar.gz" && -f "$backup_dir/SHA256SUMS" ]] || { echo "Backup is incomplete" >&2; exit 2; }
|
||||
(cd "$backup_dir" && sha256sum -c SHA256SUMS)
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"; cd "$root_dir"
|
||||
docker compose down
|
||||
mkdir -p data public
|
||||
mv data/hub.db "data/hub.db.before-restore.$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
|
||||
rm -rf public/uploads
|
||||
cp "$backup_dir/hub.db" data/hub.db
|
||||
tar -xzf "$backup_dir/uploads.tar.gz" -C public
|
||||
docker compose up -d
|
||||
printf 'Restore started from: %s\n' "$backup_dir"
|
||||
Reference in New Issue
Block a user