#!/usr/bin/env bash # # Nightly SQLite backup for the Bifrost portal. Uses the online .backup API # (safe while the app is running — consistent, no locking issues with WAL). # Keeps 30 days of compressed snapshots. # # Install as a cron job (as the `bifrost` user): # crontab -e # 15 3 * * * /opt/bifrost-portal/scripts/backup.sh >> /var/log/bifrost-backup.log 2>&1 # # Per SPEC §7.3 the offsite target is a Hetzner Storage Box; sync BACKUP_DIR # there separately (e.g. rclone/rsync in a second cron line). set -euo pipefail DB_PATH="${BIFROST_DB_PATH:-/var/lib/bifrost-portal/bifrost.db}" BACKUP_DIR="${BACKUP_DIR:-/var/lib/bifrost-portal/backups}" RETENTION_DAYS="${RETENTION_DAYS:-30}" mkdir -p "$BACKUP_DIR" stamp="$(date -u +%Y%m%d-%H%M%S)" out="$BACKUP_DIR/bifrost-$stamp.db" echo "==> Backing up $DB_PATH -> $out" sqlite3 "$DB_PATH" ".backup '$out'" gzip -f "$out" echo "==> Pruning backups older than $RETENTION_DAYS days" find "$BACKUP_DIR" -name 'bifrost-*.db.gz' -type f -mtime "+$RETENTION_DAYS" -delete echo "==> Backup complete: ${out}.gz"