diff --git a/AGENTS.md b/AGENTS.md index 1ae7189..7663bb2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2114,8 +2114,14 @@ The community relay moved off the hosted relay.tools instance - ⚠️ `relay.skate-spots.org` can show a stale NXDOMAIN in a local resolver cache right after creation (our dev box did). Verify with `curl --resolve relay.skate-spots.org:443:185.18.221.2 …` or from another host. -- **Backups:** `scripts/archive-relay.mjs` now defaults to the new relay; the - weekly timer + restic offsite are unchanged. +- **Backups:** the weekly `skatespots-archive.timer` still runs + `scripts/backup-relay.sh`, but it now archives **through an SSH tunnel** to the + relay host's `127.0.0.1:7777` (overridable via `SKATESPOTS_RELAY_SSH`; falls back + to the public URL if the tunnel can't be established), so it never depends on + public DNS resolving from the dev box. Local snapshots stay in + `~/.backups/relay` (12 kept) and restic pushes to the host's repo + (`~/.config/skatespots/restic.env`). Two locations today (relay host + dev box); + a third would need a new offsite destination. ### Git / ngit publishing - Push: `git push origin main` (handled by `git-remote-nostr`; publishes a signed repo-state event). diff --git a/scripts/backup-relay.sh b/scripts/backup-relay.sh index da597de..4528977 100755 --- a/scripts/backup-relay.sh +++ b/scripts/backup-relay.sh @@ -5,9 +5,15 @@ # Driven by the systemd user timer `skatespots-archive.timer` (install with # scripts/install-archive-timer.sh). Local archives land in # ~/.backups/relay; if ~/.config/skatespots/restic.env exists, the whole -# directory is pushed to a restic repository (S3/R2/B2/SFTP) and old snapshots -# are pruned. Without that file the archive is local-only — still useful, but -# not a real offsite backup. +# directory is pushed to a restic repository (SFTP to our own host, or any +# S3/R2/B2 store) and old snapshots are pruned. Without that file the archive is +# local-only — still useful, but not a real offsite backup. +# +# The relay lives on OUR host. The archive reaches it over an SSH tunnel to that +# host's 127.0.0.1:7777 (so it never depends on public DNS resolving from this +# machine). If the tunnel can't be established it falls back to the public URL. +# Override with SKATESPOTS_RELAY_SSH (default: the `skatespots-cvm` ssh alias) +# and SKATESPOTS_RELAY_TUNNEL_PORT (default 17777). # # Manual run / debug: # scripts/backup-relay.sh @@ -24,13 +30,39 @@ RESTIC_ENV="$HOME/.config/skatespots/restic.env" # CVM host + object storage. Same format as restic.env. RESTIC_ENV_2="$HOME/.config/skatespots/restic-2.env" +TUNNEL_PORT="${SKATESPOTS_RELAY_TUNNEL_PORT:-17777}" +SSH_TARGET="${SKATESPOTS_RELAY_SSH:-skatespots-cvm}" + log() { echo "[$(date -Is)] $*"; } mkdir -p "$ARCHIVE_DIR" cd "$REPO" +# Port-open probe (uses node, which is always on PATH here). +port_open() { + node -e 'const n=require("net");const s=n.connect(+process.argv[1],"127.0.0.1");s.on("connect",()=>{s.destroy();process.exit(0)});s.on("error",()=>process.exit(1));setTimeout(()=>process.exit(1),2000)' "$1" 2>/dev/null +} + log "archiving the community relay…" -node scripts/archive-relay.mjs +RELAY_ARG="" +TUNNEL_PID="" +ssh -N -o BatchMode=yes -o ExitOnForwardFailure=yes \ + -L "127.0.0.1:${TUNNEL_PORT}:127.0.0.1:7777" "$SSH_TARGET" >/dev/null 2>&1 & +TUNNEL_PID=$! +trap 'kill "$TUNNEL_PID" 2>/dev/null || true' EXIT +for _ in 1 2 3 4 5; do + port_open "$TUNNEL_PORT" && break + sleep 1 +done +if port_open "$TUNNEL_PORT"; then + RELAY_ARG="--relay ws://127.0.0.1:${TUNNEL_PORT}" + log " via SSH tunnel to $SSH_TARGET (localhost:7777)" +else + log " tunnel unavailable — using the public relay URL" +fi + +# shellcheck disable=SC2086 +node scripts/archive-relay.mjs $RELAY_ARG # Push the archive directory to every configured restic repo. Each is sourced in # its own subshell so RESTIC_* variables don't leak between destinations.