Skip to content

Storage — proxfold

Storage architecture for proxfold: the boot mirror, the primary ZFS media pool, NFS export to arrstack, and the NAS used for Proxmox backups.

Boot mirror (rpool)

Property Value
Pool name rpool
Layout ZFS mirror (RAID1)
Disks Samsung SM843T 960GB + Intel DC S4500 960GB (SATA)
Mount point / (plus /rpool, /rpool/ROOT, /rpool/data, /var/lib/vz)
Usable capacity ~888 GB
Current usage (sampled 2026-04-28) ~25 GB allocated / ~836 GB free (2% full)
Proxmox storage IDs local (dir on rootfs, ISO/template/vztmpl) + local-zfs (ZFS-backed disk images for VMs/CTs)

Installed via the Proxmox auto-installer during the Phase 4C boot drive swap (2026-04-22). The disk filter in rebuild/answer.toml.j2 selects both drives via filter.ID_BUS="ata"; the installer builds the mirror as ashift=12 with the PVE 9 defaults (compression=on, atime=off, relatime=on).

Check mirror health:

zpool status rpool
proxmox-boot-tool status   # both ESPs should show "uuid=... is configured with: grub"

ZFS Pool (stash)

Property Value
Pool name stash
Layout RAIDZ1
Disks 6x Samsung PM1633a 3.84TB SAS SSD (expanded from 4-wide 2026-04-20)
Mount point /stash
Media path /stash/rodneystash/
Usable capacity ~21 TB (RAIDZ1 on 6× 3.84 TB SSDs)
Current usage (sampled 2026-04-28) ~13.1 TB allocated / ~7.9 TB free (62% full)
ZFS version zfs-2.4.1-pve1 userland / zfs-kmod-2.3.4-pve1 — split is expected on PVE 9.1 and is backward-compatible

Expansion parity ratio

Data written before the expansion keeps its original 4-wide parity ratio (3d+1p). Only new writes use the 6-wide ratio (5d+1p). Reported usage will slowly improve as old data is rewritten (replaced, moved, or re-encoded) — this is a cosmetic accounting quirk, not a real space loss.

No offsite or incremental backup

Media on stash/rodneystash/ is protected by RAIDZ1 only. There is no offsite copy and PBS does not back up bulk media. See Accepted Risks — Media library has no backup for the tradeoff and the conditions that would trigger a revisit.

Datasets

NAME              USED    AVAIL  REFER  QUOTA   MOUNTPOINT
stash             ~9.32T  ~5.78T ~9.32T none    /stash
stash/plex-data   ~8.92G  ~91.1G ~8.92G 100G    /stash/plex-data
Dataset Purpose Quota
stash Root dataset — media files at /stash/rodneystash/ none
stash/plex-data Plex data directory (metadata, databases, cache, logs) 100G

The plex-data child dataset was created to move Plex's data directory off the LXC rootfs. See Plex — data directory for full details.

# Monitor dataset usage
zfs list -r stash -o name,used,avail,refer,quota

Media directories

/stash/rodneystash/
├── Movies/
├── TV Shows/
└── Downloads/

Check pool health

zpool status stash

ZFS scrub

Scrubs run on an automatic schedule. To trigger manually:

zpool scrub stash

ZFS ARC cap

By default ZFS will grow the ARC cache to consume most available RAM. With 48GB total RAM and both rpool + stash as ZFS pools, a cap is applied:

echo "options zfs zfs_arc_max=15032385536" > /etc/modprobe.d/zfs.conf
update-initramfs -u
# Takes effect after reboot

Current value: 14 GB (15032385536). Reference table:

Desired max Byte value
4 GB 4294967296
8 GB 8589934592
12 GB 12884901888
14 GB 15032385536
16 GB 17179869184

Verify after reboot:

grep "^c_max" /proc/spl/kstat/zfs/arcstats

Note

The stash pool workload is mostly sequential media reads (low ARC hit rate). 14 GB is the current cap on 48 GB total RAM, leaving headroom for VMs and containers.

zpool upgrade — completed 2026-04-20

zpool upgrade stash was run at the start of Phase 3 RAIDZ expansion (2026-04-20 13:54 ACST). Five feature flags were enabled: raidz_expansion, redaction_list_spill, fast_dedup, longname, large_microzap. This is irreversible — the pool now requires OpenZFS 2.3+ to import. Any rescue or recovery environment must boot a kernel with ZFS 2.3 or newer.

NFS Export

The ZFS pool is exported via NFS to the arrstack VM.

/etc/exports:

/stash 192.168.1.252(rw,sync,no_subtree_check,no_root_squash)
  • Only arrstack (192.168.1.252) is permitted to mount the export
  • no_root_squash is used because containers run as PUID=0 on a trusted home network

To reload exports after a change:

exportfs -ra

NFS Mount (arrstack VM)

Configured in /etc/fstab on the arrstack VM:

192.168.1.250:/stash  /stash  nfs  defaults,_netdev  0  0

Mounts at /stash inside the VM, matching the host path.

SMB Export

One read-write SMB share \\192.168.1.250\media from the dataset root for Windows client access (DaVinci Resolve clip ingest, Music drag-and-drop). Managed by the samba role.

Property Value
Share name media
Path /stash/rodneystash
Access Authenticated, read-write
User smbmedia (system user, nologin; password in vault)
Force user root (traverses across mixed-PUID files from the arrstack containers)
Allowed network 192.168.1.0/24
Protocol minimum SMB2 (SMB1 disabled)

Connect from Windows: File Explorer → Map Network Drive → \\192.168.1.250\media, "Connect using different credentials", store in Credential Manager. Writes from Windows land as root:root 0644; Plex / Sonarr / Radarr keep consuming via the same dataset path.

Why not separate read-only and read-write shares?

The first cut of this share split read-only (Movies / TV Shows) from read-write (Music). It ran straight into Windows' SMB MUP limit: one credential set per server identity, even with identical creds. System error 1219 — "Multiple connections to a server or shared resource by the same user…" — per Microsoft's troubleshooting guide. Workarounds (DNS CNAME / hosts-file alias / NetBIOS hostname for one mount and IP for the other) work but add a moving part. The simpler call: drop the split, accept that Windows drag-delete can now hit Movies/ and TV Shows/. The arrstack containers already have full write access to those paths, so the read-only safety was never load-bearing — it just felt nice.

Proxmox Mount Points (Plex LXC)

The ZFS pool and Plex data dataset are mounted directly into the plex LXC via Proxmox mount points, bypassing NFS:

mp0: /stash,mp=/stash
mp1: /stash/plex-data,mp=/stash/plex-data

See Plex for how media paths and the data directory are exposed inside the container.

LXC rootfs reclamation

Since Phase 4C the rootfs for LXC containers lives on local-zfs (backed by rpool/data), not LVM-thin. ZFS reclaims freed blocks natively through copy-on-write, so the old weekly pct fstrim cron the host used to carry is no longer required and is not deployed on the rebuilt host.

Historical context

Pre-2026-04-22 the boot drive was a single 128GB Samsung 840 PRO in LVM-thin, and a weekly Sunday 03:00 pct fstrim cron ran on all running containers to reclaim space (LVM-thin does not auto-return freed blocks, and discard=on is not valid on LXC rootfs). If you roll back to an LVM-thin boot drive for any reason, re-add the cron.

NAS-backed backup storage

The QNAP TS-269L at 192.168.1.253 is the only second failure domain in the lab. Two Proxmox storage entries point at it, with different roles since Phase 5A:

Storage ID Type Content Status
nas-primary PBS VM/CT incremental backups via Proxmox Backup Server Primarypbs-daily runs nightly 02:00 ACST against this; managed via the pbs role and the proxmox role's pbs_client.yml task. Datastore lives on PBS CT 105 over NFSv3 from the QNAP.
nasbackup CIFS vzdump archives (legacy) Transitional — kept registered through ~2026-05-23 for the 30-day PBS-only soak called out in Phase 5A. Slated for removal once the PBS path has run unattended through that window. Codified in the proxmox role for idempotent re-registration during the transition.

QNAP details (applies to both):

Property Value
IP 192.168.1.253
Configuration 2× drives, RAID 1
Shares used backup (CIFS for nasbackup; NFS export for nas-primary via PBS CT)
Firmware QTS 4.3.4 (EOL — see Accepted Risks — QNAP firmware EOL)

Equivalent manual nasbackup registration (for reference; the role handles this idempotently):

pvesm add cifs nasbackup --server 192.168.1.253 --share backup --username admin --password '<password>' --content backup --smbversion 2.0

PBS-side datastore mount and ACL detail live in the pbs role page.