Storage Architecture¶
Last updated: 2026-06-23
Storage Classes¶
| StorageClass | Provisioner | Access Mode | Use Case |
|---|---|---|---|
longhorn (default) |
driver.longhorn.io | RWO | App config, databases — replicated across 3 nodes |
nfs-media |
nfs-subdir-external-provisioner | RWX | Shared data, media, receipts, downloads |
Longhorn¶
Distributed block storage, replicated 3x across nebula nodes.
- Replication: 3 replicas — survives 2-node failure
- Access mode: RWO (ReadWriteOnce) — single pod at a time
- Use case: All stateful app configs (sonarr, radarr, plex, etc.)
- Total capacity: ~4,675 GB across 5 nodes — 14% scheduled (as of 2026-06-23)
Health check:
All volumes should showrobustness: healthy.
NFS (TrueNAS)¶
- Server: 192.168.1.200
- Base path:
/mnt/Arr1/SMB/ - Dynamic provisioning: nfs-subdir-external-provisioner creates subdirectories per PVC
- Static PVs: movies, tv, anime, music, audiobooks, roms (direct NFS mounts)
- Access mode: RWX (ReadWriteMany) — shared across all pods/nodes
NFS PV manifests require spec.nfs.server to be an IP address — DNS names are not supported by the NFS driver. The raw IP 192.168.1.200 in PV manifests is intentional and immutable after creation.
Current Storage Patterns¶
| Service | Storage | Access Mode | Notes |
|---|---|---|---|
| Media apps (sonarr, radarr, etc.) | Longhorn PVC | RWO | Config only — media files on NFS |
| Media files | NFS static PVs | RWX | movies, tv, music, etc. |
| Receipts images | NFS dynamic PVC | RWX | /mnt/Arr1/SMB/receipts/ |
| heezy-finance | No PVC | — | Stateless — all data in Postgres |
| Gitea | Longhorn PVC | RWO | gitea namespace |
| OpenBao | Longhorn PVC | RWO | openbao namespace, Raft storage |
| Postgres (big-boi) | Host bind mount | — | /opt/ on big-boi, not in k8s |
VPN Sidecar Storage Note¶
slskd-vpn and qbittorrent-vpn use pod affinity to co-locate with their RWO PVCs. This is intentional — the PVC can only be mounted on one node at a time. If you move these pods, the PVC must follow.
Recommendations¶
- Never use
nodeSelectorto work around RWO PVC constraints — convert to NFS RWX or restructure to keep state in Postgres - Longhorn is vastly underutilized — 4+ TB available, no capacity concern for foreseeable future
- NFS at 80% (38TB/48TB) — monitor, add alert at 90%