Files
ansible-pull-deploy/plans/06-data-and-persistence.md
Artemis (Iron Legion) d60bc96f1d Add homelab services stack PRD
Verifies 16 DockerHub images, assigns target nodes per locked policy,
defines 3-phase deployment order (Infra → Media → Polish),
and captures open questions for Bobby.

Services: Traefik, Technitium DNS, AdGuard Home, Prometheus, Grafana,
Beszel, Dozzle, Portainer, Homepage, Authelia, Vaultwarden, Jellyfin,
Sonarr, Radarr, Prowlarr, Nextcloud

Domain: *.ai.home
No public internet exposure.
2026-05-25 17:17:23 -04:00

2.7 KiB
Raw Blame History

Iron Legion Homelab Services Stack — Data & Persistence

Volume Strategy

Every service with persistent state uses bind mounts to on-node directories. No named volumes, no NFS, no distributed storage.

Directory Convention

/opt/iron-legion/
├── service-name/
│   ├── data/           # Application data (databases, config, state)
│   ├── config/         # Static config files mounted read-only where possible
│   └── logs/           # Log output (optional, if not sent to stdout)

Per-Service Persistence

Service Data Path Backup Target Size Estimate
Traefik /opt/iron-legion/traefik/config/ /opt/iron-legion/traefik/certs/ Bones (daily rsync) < 50 MB
Technitium DNS /opt/iron-legion/technitium/config/ Bones < 10 MB
Pi-hole /opt/iron-legion/pihole/etc-pihole/ /opt/iron-legion/pihole/etc-dnsmasq.d/ Bones < 500 MB
Prometheus /opt/iron-legion/prometheus/data/ Bones (retention: 15d local, 90d backup) 520 GB
Grafana /opt/iron-legion/grafana/data/ Bones < 500 MB
Beszel /opt/iron-legion/beszel/data/ Bones < 1 GB
Portainer /opt/iron-legion/portainer/data/ Bones < 100 MB
Homepage /opt/iron-legion/homepage/config/ Bones < 10 MB
Vaultwarden /opt/iron-legion/vaultwarden/data/ Bones (encrypted) < 500 MB
Authelia /opt/iron-legion/authelia/config/ Bones < 10 MB
Jellyfin /opt/iron-legion/jellyfin/config/ /opt/iron-legion/jellyfin/media/ None (media too large) < 1 GB config; media drive separate
Sonarr /opt/iron-legion/sonarr/config/ Bones < 1 GB
Radarr /opt/iron-legion/radarr/config/ Bones < 1 GB
Prowlarr /opt/iron-legion/prowlarr/config/ Bones < 100 MB
Nextcloud /opt/iron-legion/nextcloud/data/ Bones (snapshots) 1050 GB

Media Storage Exception

  • Jellyfin media lives on a separate mount (likely external USB/NVMe on Mark44). Not backed up via rsync.
  • Sonarr/Radarr download staging to a shared /downloads bind mount, then hardlink/copy to Jellyfin media library.

Backup Tooling

  • Primary: rsync -a --delete to Bones secondary storage daily at 03:00 local.
  • Vaultwarden: rsqlite3 dump + rsync (encrypted at rest on Bones).
  • Prometheus: snapshot API → rsync (not raw WAL files).

Secret Management

  • .env files live in /opt/iron-legion/service-name/.env, mode 0600.
  • Compose files use ${VAR_NAME} syntax, never literal strings.
  • Vaultwarden stores shared secrets (DB passwords, API keys). Artemis holds no secrets in memory.