Rebuild · Build Atlas DRAWING 01 / 06
STAGE 01 / GATE BLOCKING ~30 min · 0 credits

Precheck.

Nothing gets wiped until every item ticks and S3 is verified. This is the gate between planning and doing — a forcing function before any irreversible action.

Prerequisites — complete before this stage

01 · Infisical setup — cloud account, CLI logged in, AWS credentials stored.
02 · Terraform AWS — S3 buckets provisioned, Restic IAM user created.
All aws and restic commands below inject credentials via infisical run --env=prod --.

Goal

Every critical artefact is in S3 — and a restore has been spot-checked.

No rebuild work begins until this stage clears. Two buckets must exist (fast + slow). One file must be successfully read back.

Exit criteria
  • Both S3 buckets accessible and confirmed private
  • Vault, runner code, configs, secrets, repos, DBs, compose files all in S3
  • Photos in slow bucket (Glacier IR)
  • One restore proven by reading a file back
  • Total backup size noted in vault
Drawing 01.A — Backup Topology

What goes where

CONTABO VPS obsidian-vault /root/obsidian-vault runner code /opt/runner config + .env secrets — encrypt HOMELAB · PROD VM gitea repos · pg dumps /opt/docker · /etc/nginx Restic / aws s3 encrypt · dedupe tag: precheck homelab-backup-fast S3 STANDARD vault · runner · gitea · dbs 7d / 4w / 3m homelab-backup-slow S3 GLACIER IR photos · plex meta 4w / 12m Spot-check aws s3 cp ↓ cat · diff · sign-off Encrypted · private · restorable. No rebuild starts until the spot-check passes.
Sign-off Gate

12-Item Checklist

0% 0 / 12
  • S3 buckets accessible and confirmed privateStep 1
  • Obsidian vault backed up and verified in S3Step 2
  • Current runner code backed upStep 3
  • Runner config.yaml and .env backed up (private bucket)Step 4
  • Gitea repos backed upStep 5
  • PostgreSQL databases dumped and in S3Step 6
  • Docker Compose files backed upStep 7
  • Nginx configs backed upStep 7
  • Photos in slow bucket (Glacier IR)Step 8
  • Plex metadata backed upStep 9
  • Spot-check restore passed (one file read back)Step 11
  • Total backup size noted in vaultStep 12
Drawing 01.B — Operations

Commands by step

infisical run --env=prod -- aws s3 ls s3://homelab-backup-fast
infisical run --env=prod -- aws s3 ls s3://homelab-backup-slow
infisical run --env=prod -- aws sts get-caller-identity
# Restic preferred
infisical run --env=prod -- restic -r s3:s3.amazonaws.com/homelab-backup-fast \
  backup /root/obsidian-vault --tag precheck --tag manual

# Or fall back to plain s3 sync
infisical run --env=prod -- aws s3 sync /root/obsidian-vault \
  s3://homelab-backup-fast/manual-precheck/obsidian-vault/
infisical run --env=prod -- aws s3 sync /opt/runner \
  s3://homelab-backup-fast/manual-precheck/runner-current/

infisical run --env=prod -- aws s3 cp /opt/runner/config.yaml \
  s3://homelab-backup-fast/manual-precheck/runner-config.yaml
infisical run --env=prod -- aws s3 cp /opt/runner/.env \
  s3://homelab-backup-fast/manual-precheck/runner-env.txt
# Easiest: Gitea's own dump
gitea dump -c /etc/gitea/app.ini --file /tmp/gitea-dump.zip
infisical run --env=prod -- aws s3 cp /tmp/gitea-dump.zip \
  s3://homelab-backup-fast/manual-precheck/gitea-dump.zip
pg_dumpall -U postgres > /tmp/all-databases.sql
infisical run --env=prod -- aws s3 cp /tmp/all-databases.sql \
  s3://homelab-backup-fast/manual-precheck/databases/all-databases.sql
rm /tmp/all-databases.sql
# Glacier Instant — slow tier
infisical run --env=prod -- aws s3 sync /path/to/photos/ \
  s3://homelab-backup-slow/manual-precheck/photos/ \
  --storage-class GLACIER_IR

infisical run --env=prod -- aws s3 sync \
  "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/" \
  s3://homelab-backup-fast/manual-precheck/plex-metadata/ \
  --exclude "Cache/*" --exclude "Codecs/*"
mkdir /tmp/restore-test
infisical run --env=prod -- aws s3 cp \
  s3://homelab-backup-fast/manual-precheck/obsidian-vault/HOMELAB-CURRENT-STATE-2026-05-04.md \
  /tmp/restore-test/
cat /tmp/restore-test/HOMELAB-CURRENT-STATE-2026-05-04.md
rm -rf /tmp/restore-test
# Worst-case rollback to current state
infisical run --env=prod -- aws s3 sync s3://homelab-backup-fast/manual-precheck/obsidian-vault/ /root/obsidian-vault/
infisical run --env=prod -- aws s3 sync s3://homelab-backup-fast/manual-precheck/runner-current/ /opt/runner/
infisical run --env=prod -- aws s3 cp   s3://homelab-backup-fast/manual-precheck/runner-env.txt   /opt/runner/.env

systemctl restart obsidian-runner obsidian-runner-web
Risks

Things that bite

CRITICAL

.env public

Bucket must be private. Verify in console before uploading runner-env.txt.

WATCH

Photo upload time

Multi-GB libraries take hours. Run in tmux, check size with --summarize.

WATCH

Restore not tested

A backup with an untested restore is not a backup. Step 11 is non-optional.

← Atlas NEXT · Stage 02
Foundations →