--- schema_version: 1 id: home-server.backups type: reference scope: [jupiter, backrest, restic, google-drive, recovery] sensitivity: private-infrastructure last_reviewed: "2026-10-06" sources: - kind: owner-report reference: "Backrest plan JSON, destination, key custody and no restore test, 2026-10-06" - kind: owner-report reference: "Updated four-service Backrest plan and deployed Portainer bind mount/container name, 2026-10-06" - kind: owner-report reference: "Only restic key has independent custody; no independent credential recovery or backup/restore evidence, 2026-10-06" - kind: repository repository: jupiter-stacks revision: 610e325ef6a98850511ce7a089b0b9a77bfecf15 paths: - stacks/backrest/docker-compose.yml - stacks/gitea/docker-compose.yml - stacks/paperless-ngx/docker-compose.yml - stacks/vaultwarden/docker-compose.yml related: [home-server.reference, home-server.storage, home-server.portainer, home-server.authentication, home-server.operations] update_triggers: [backup-plan-change, destination-change, hook-change, credential-change, restore-test] unknowns: - last-successful-backup-and-repository-check - google-drive-repository-path - measured-rpo-and-rto --- # Backups | Setting | Value | | --- | --- | | Engine | Backrest / restic; plan `jupiter-backup` | | Repository | `jayo60013-gdrive`; Google Drive; account `jayo60013` | | Schedule | `0 3 * * *`; UTC; daily 03:00 | | Retention | `policyKeepLastN: 4`; last four snapshots, not four days | | Encryption key | iCloud password app; no key stored here | | Independent credential recovery | None beyond the restic encryption key | | Backup / integrity evidence | None supplied | | Restore test | Never performed | ## Coverage Backrest bind-mounts host `/data` at container `/userdata:ro`. | Host source | Plan path | | --- | --- | | `/data/gitea` | `/userdata/gitea` | | `/data/paperless-ngx` | `/userdata/paperless-ngx` | | `/data/portainer` | `/userdata/portainer` | | `/data/vaultwarden` | `/userdata/vaultwarden` | Case-insensitive exclusion: `/userdata/gitea/gitea/packages`. `excludes: []`; CLI `--skip-if-unchanged` supplied despite plan `skipIfUnchanged: false`. Unchanged runs may create no snapshot. ## Consistency hooks Stop timeout `120s`; chains use `&&`. Errors: `ON_ERROR_FATAL`, except Portainer restart (`ON_ERROR_IGNORE`). | Event | Ordered commands / containers | | --- | --- | | `SNAPSHOT_START` | Stop `paperless` -> `paperless_db` | | `SNAPSHOT_START` | Stop `gitea_runner` -> `gitea` -> `gitea_db` | | `SNAPSHOT_START` | Stop `vaultwarden` | | `SNAPSHOT_START` | Stop `portainer` | | `SNAPSHOT_END`, `SNAPSHOT_ERROR` | Start `paperless_db` -> `paperless` | | `SNAPSHOT_END`, `SNAPSHOT_ERROR` | Start `gitea_db` -> `gitea` -> `gitea_runner` | | `SNAPSHOT_END`, `ANY_ERROR` | Start `vaultwarden` | | `SNAPSHOT_END`, `SNAPSHOT_ERROR` | Start `portainer`; ignore hook failure | Cold filesystem copies of applications/databases; no database dumps supplied. Broker stays running. `docker start` does not wait for database readiness. Hook failure can leave services stopped; recovery is not demonstrated. Portainer restart failure does not fail the backup operation. ## Backrest state | Host path | Container path | | --- | --- | | `/data/backrest/data` | `/data` | | `/data/backrest/config` | `/config`; plan/repository configuration `config.json` | | `/data/backrest/rclone` | `/root/.config/rclone` | | `/home/jay/data/backrest/cache` | `/cache` | | `/data/backrest/restore` | `/restore` | | `/var/run/docker.sock` | `/var/run/docker.sock`; lifecycle hooks | ## Recovery limits Only the four listed directories are covered. No supplied coverage for Authelia, Traefik, Backrest configuration, Docker named volumes, OS, or Mercury. Full-host recovery requires independently retrievable repository credentials, configuration and restic key. Key custody alone does not establish recoverability. No independent Google Drive/rclone credential recovery or Backrest-config recovery arrangement exists. Recovering backed-up Portainer state is not a substitute for first being able to retrieve the backup. `/restore` is on the same RAID array; not an independent backup.