Skip to content

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:

kubectl get volumes.longhorn.io -n longhorn-system
All volumes should show robustness: 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 nodeSelector to 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%