hephaestus/scripts/backup-restic.sh
2026-09-12 00:07:28 +02:00

51 lines
2 KiB
Bash

#!/usr/bin/env bash
# Nightly backup of Forgejo state to a second sia.storage bucket via restic.
# Belt-and-suspenders: sia.storage's ToS caps liability at ~$100 and doesn't
# guarantee data retention on account termination. This is our recoverability.
#
# Contents:
# - /data/git (bare repos on VPS local disk)
# - postgres (pg_dump of the forgejo database)
#
# Restic itself lives in a small sidecar container; this script is intended to
# be scheduled via `cron` on the VPS host, or `docker compose exec` from a
# systemd timer. See docker-compose.override.yml.example (todo) for wiring.
#
# Retention: keep-daily=7 keep-weekly=4 keep-monthly=12
set -euo pipefail
# shellcheck disable=SC1091
[[ -f "$(dirname "$0")/../.env" ]] && source "$(dirname "$0")/../.env"
: "${SIA_STORAGE_ENDPOINT:?}"
: "${SIA_STORAGE_ACCESS_KEY:?}"
: "${SIA_STORAGE_SECRET_KEY:?}"
: "${SIA_STORAGE_BUCKET_BACKUP:=${SIA_STORAGE_BUCKET}-backup}"
: "${RESTIC_PASSWORD:?RESTIC_PASSWORD must be set in .env (generate with: openssl rand -base64 32)}"
export AWS_ACCESS_KEY_ID="$SIA_STORAGE_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="$SIA_STORAGE_SECRET_KEY"
export RESTIC_REPOSITORY="s3:https://${SIA_STORAGE_ENDPOINT}/${SIA_STORAGE_BUCKET_BACKUP}"
export RESTIC_PASSWORD
# Init on first run (idempotent — swallows "already initialised")
restic snapshots >/dev/null 2>&1 || restic init
# 1. Postgres dump (pipe into restic's stdin backup mode)
docker compose exec -T postgres pg_dump -U "${POSTGRES_USER}" "${POSTGRES_DB}" \
| restic backup --stdin --stdin-filename postgres-forgejo.sql --tag postgres
# 2. Git repositories (mounted volume path inside the forgejo container)
docker compose exec forgejo tar -cf - /data/git \
| restic backup --stdin --stdin-filename forgejo-git.tar --tag git
# 3. Prune old snapshots
restic forget --prune \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12
# 4. Verify a sample of the repo (cheap integrity check)
restic check --read-data-subset=5%
echo "backup ok at $(date -Iseconds)"