Skip to content

Data

Two trees per app — config and data — cleanly separated so backups can target the bytes that change. This document is canonical; paths elsewhere should be read against it.

The rule

tree holds changes backed up
config compose files, .env, .env.example, scripts, unit drop-ins rarely, deliberately git (the repo is the config backup) + nightly config snapshot
data application state: databases, libraries, uploads, caches, tokens constantly nightly restic

Naming: lowercase, no separators in the app name, one directory per app, data directory named exactly like the config directory.

The roots

node config root data root
vps-apps /opt/homelab/vps-apps/<app>/ (tracked) + /opt/docker/<app>/ (untracked) /opt/homelab-data/<app>/
vps-net /opt/homelab/vps-net/<app>/ /opt/homelab-data/<app>/
pi-home systemd units + /etc/<app>/ /mnt/dietpi_userdata/<app>/

Ground rules

  • No application data under /opt/docker. If a directory there holds anything but config, it is a violation; move it to the node's data root.
  • Named Docker volumes on vps-apps become bind mounts into /opt/homelab-data/<app>/. A volume you cannot see in the filesystem is a volume you cannot back up with a path-based plan.
  • Cloud mounts (/mnt/gdrive, /mnt/altdrive, /mnt/pcloud) are not app data. External sources. An app may point at them read-only (e.g. romm's library on pCloud); it may not store its state there.
  • /home/jmrdez and /home/dietpi are not data roots.

Backup split

Two hosts × two branches × two locations. Restic repos are encrypted and versioned. Repos are named <host>-<branch>-<loc>; the tree is nested on both locations:

pi-hdd  (pi-home HDD, /mnt/pi-hdd/backups — physical)
gdrive:backups (— off-site, same shape)
  <host>/{config,data}/
host engine schedule (Madrid) retention
vps-apps Backrest (Docker, 4 plans) config 04:00 pihdd / 05:00 gdrive · data 03:30 pihdd / 04:30 gdrive config d14/w8/m12 · data d7/w4/m6
pi-home native restic-pihome-backup + timers data 02:00 / config 02:30 (node clock UTC: 00:00/00:30) config d14/w8/m12 · data d7/w4/m6
  • pi-hdd is the fast local leg; gdrive the off-site leg (~1 h later).
  • One repo password per branch, shared across both locations, stored on the node only (vps-apps: /opt/docker/backrest/repo-password-{config,data}, pi-home: /etc/restic-backups/{config,data}.pass, both chmod 600).
  • All eight repos verified. pi-home has no Docker and no Backrest — restic-backup@.service template unit + two timers, ntfy push on failure, weekly forget+prune with MemoryMax=300M.
  • RomM assets ride the vps-apps data plans from the pCloud FUSE mount. A FUSE hang can stall a plan for up to 1 h/file; recovery is systemctl restart rclone-pcloud.service.

Not backed up (deliberately)

  • pi-home /mnt/pi-hdd/share/{open,temp} — the WebDAV drop (vps-apps/ webdav/). Scratch data, disposable.
  • Crucially: nothing else is excluded by design. If a new app holds data, it joins the restic set. No exceptions.

OpenCloud — stays local

/opt/homelab-data/opencloud/ on vps-apps, backed up nightly via the data branch (pihdd + gdrive). Keep it on the local disk: a network FS (NFS) panics the reva/NATS dataprovider in the ocis container — this was tried, failed, and reverted. Do not retry.