#!/bin/bash # # Daily PocketBase point-in-time backup โ€” CLAUDE.md ยง18 "Layer 2 โ€” # Daily zip backup". Belt-and-braces alongside Litestream's real-time # WAL streaming (Layer 1): this is the fallback if the Litestream # stream itself is ever corrupted, so it deliberately does NOT depend # on Litestream being healthy. # # Installed on the Hetzner VPS at /usr/local/bin/backup-pocketbase.sh, # triggered by the crontab entry in bettersight-backup.cron. # # Requires: rclone configured with a remote named "hetzner-s3" pointing # at the Hetzner Object Storage bucket (see .env.example's # HETZNER_S3_* vars for the credentials that remote should use). set -euo pipefail DATE=$(date +%Y%m%d) BACKUP_NAME="backup_${DATE}.zip" docker exec pocketbase /pb/pocketbase backup \ --dir /pb/backups --name "${BACKUP_NAME}" rclone copy /pb/backups/ \ hetzner-s3:bettersight-backups/ \ --max-age 7d # 7-day retention on Hetzner Object Storage (via --max-age above) plus # a tighter 2-day local retention on the VPS itself โ€” the local copy # only needs to survive long enough for the rclone upload to succeed. find /pb/backups -name "*.zip" -mtime +2 -delete