chore(backup): support a second offsite repo (restic-2.env)
backup-relay.sh now pushes the archive to restic.env AND, if present, restic-2.env — so adding an R2/B2 bucket gives true 3-2-1 (local + CVM + object storage) instead of replacing one offsite with another. Each repo is sourced in its own subshell so RESTIC_* don't leak between them. Verified with a throwaway local second repo: both pushes ran, both snapshots exist. Also documents the umask trap (mode-600 cache dirs break restic).
This commit is contained in:
parent
08189a71af
commit
5b63a69a2c
3 changed files with 37 additions and 13 deletions
10
AGENTS.md
10
AGENTS.md
|
|
@ -732,8 +732,14 @@ Rules:
|
||||||
`~/.config/skatespots/cvm.env`) so no key/host lives in tracked files.
|
`~/.config/skatespots/cvm.env`) so no key/host lives in tracked files.
|
||||||
`~/.config/skatespots/restic.env` (600, outside the repo) holds the repo URL +
|
`~/.config/skatespots/restic.env` (600, outside the repo) holds the repo URL +
|
||||||
the generated `RESTIC_PASSWORD` — **that password is required to restore; keep a
|
the generated `RESTIC_PASSWORD` — **that password is required to restore; keep a
|
||||||
copy in a password manager**. A second offsite (Cloudflare R2) can be added by
|
copy in a password manager**. A second offsite is supported: put another repo
|
||||||
pointing the same file at an S3 repo.
|
(e.g. Cloudflare R2 / Backblaze B2) in **`~/.config/skatespots/restic-2.env`**
|
||||||
|
and `backup-relay.sh` pushes to **both** — true 3-2-1 (local + CVM + object
|
||||||
|
storage). Verified 2026-09-28 with a throwaway second repo.
|
||||||
|
- ⚠️ **Don't run restic under a restrictive `umask`.** restic creates its cache
|
||||||
|
dirs from the umask, and a mode-600 dir has no execute bit → "permission
|
||||||
|
denied" on `~/.cache/restic/<repo>/version`. If it happens:
|
||||||
|
`find ~/.cache/restic -type d ! -perm -u+x -exec chmod u+rwx {} +`.
|
||||||
- **Restore drill (proven 2026-09-28):** `node scripts/drill-relay.mjs [port]`
|
- **Restore drill (proven 2026-09-28):** `node scripts/drill-relay.mjs [port]`
|
||||||
starts a throwaway in-memory NIP-01 relay (`ws`, no persistence); then
|
starts a throwaway in-memory NIP-01 relay (`ws`, no persistence); then
|
||||||
`node scripts/restore-relay.mjs <archive> --to ws://localhost:<port>` and query
|
`node scripts/restore-relay.mjs <archive> --to ws://localhost:<port>` and query
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ export PATH="/home/sovereignsk8/.nvm/versions/node/v22.23.1/bin:$PATH"
|
||||||
|
|
||||||
ARCHIVE_DIR="${SKATESPOTS_ARCHIVE_DIR:-$HOME/.backups/relay}"
|
ARCHIVE_DIR="${SKATESPOTS_ARCHIVE_DIR:-$HOME/.backups/relay}"
|
||||||
RESTIC_ENV="$HOME/.config/skatespots/restic.env"
|
RESTIC_ENV="$HOME/.config/skatespots/restic.env"
|
||||||
|
# Optional SECOND offsite (e.g. an R2/B2 bucket) so we get true 3-2-1: local +
|
||||||
|
# CVM host + object storage. Same format as restic.env.
|
||||||
|
RESTIC_ENV_2="$HOME/.config/skatespots/restic-2.env"
|
||||||
|
|
||||||
log() { echo "[$(date -Is)] $*"; }
|
log() { echo "[$(date -Is)] $*"; }
|
||||||
|
|
||||||
|
|
@ -29,17 +32,28 @@ cd "$REPO"
|
||||||
log "archiving the community relay…"
|
log "archiving the community relay…"
|
||||||
node scripts/archive-relay.mjs
|
node scripts/archive-relay.mjs
|
||||||
|
|
||||||
if [ -f "$RESTIC_ENV" ]; then
|
# Push the archive directory to every configured restic repo. Each is sourced in
|
||||||
# shellcheck disable=SC1090
|
# its own subshell so RESTIC_* variables don't leak between destinations.
|
||||||
set -a; . "$RESTIC_ENV"; set +a
|
copy_offsite() {
|
||||||
|
local envfile="$1"
|
||||||
|
[ -f "$envfile" ] || return 0
|
||||||
|
(
|
||||||
|
set -a; . "$envfile"; set +a
|
||||||
if [ -z "${RESTIC_REPOSITORY:-}" ]; then
|
if [ -z "${RESTIC_REPOSITORY:-}" ]; then
|
||||||
log "restic.env present but RESTIC_REPOSITORY is empty — skipping offsite copy"
|
log " $(basename "$envfile"): no RESTIC_REPOSITORY — skipping"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
log "pushing to restic $RESTIC_REPOSITORY…"
|
log " → $RESTIC_REPOSITORY"
|
||||||
restic backup --tag skatespots-relay "$ARCHIVE_DIR"
|
restic backup --tag skatespots-relay "$ARCHIVE_DIR"
|
||||||
restic forget --tag skatespots-relay --keep-last 12 --prune
|
restic forget --tag skatespots-relay --keep-last 12 --prune
|
||||||
log "offsite copy done"
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -f "$RESTIC_ENV" ] || [ -f "$RESTIC_ENV_2" ]; then
|
||||||
|
log "pushing offsite copies…"
|
||||||
|
copy_offsite "$RESTIC_ENV"
|
||||||
|
copy_offsite "$RESTIC_ENV_2"
|
||||||
|
log "offsite copies done"
|
||||||
else
|
else
|
||||||
log "no $RESTIC_ENV — archive kept local-only (set one up for a real offsite backup)"
|
log "no $RESTIC_ENV — archive kept local-only (set one up for a real offsite backup)"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
# Configured here: the CVM host over SFTP using the `skatespots-cvm` ssh alias
|
# Configured here: the CVM host over SFTP using the `skatespots-cvm` ssh alias
|
||||||
# (see AGENTS.md → Relay archive).
|
# (see AGENTS.md → Relay archive).
|
||||||
#
|
#
|
||||||
|
# Optional SECOND offsite: copy this file to ~/.config/skatespots/restic-2.env
|
||||||
|
# and point it at another repo (e.g. Cloudflare R2 / Backblaze B2). backup-relay.sh
|
||||||
|
# pushes to BOTH, so you get true 3-2-1: local + CVM host + object storage.
|
||||||
|
#
|
||||||
# One-time init, from this machine:
|
# One-time init, from this machine:
|
||||||
# set -a; . ~/.config/skatespots/restic.env; set +a
|
# set -a; . ~/.config/skatespots/restic.env; set +a
|
||||||
# restic init
|
# restic init
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue