Homelab NAS Server
72 TB of redundant storage on TrueNAS Scale with ZFS
01. Overview
After years of external hard drives scattered across two desks and a closet shelf, I decided to consolidate everything into a single, redundant, always-on network storage system. The result is a purpose-built TrueNAS Scale server that lives in a 6U rack shelf, provides 72 usable terabytes of ZFS storage, and hosts several containerised services behind it.
The goals were simple: survive two simultaneous drive failures without data loss, keep rebuild times manageable, and give every device on the network fast access to media, backups, and shared files — without paying a cloud provider monthly.
02. Hardware Spec
| Component | Spec |
|---|---|
| CPU | AMD Ryzen 5 5600G (6-core, iGPU for Plex transcoding) |
| RAM | 64 GB DDR4-3200 ECC (4 × 16 GB) |
| Motherboard | ASRock B550M Pro4 |
| Boot Drive | 500 GB NVMe SSD (OS + apps) |
| Data Pool | 6 × 16 TB Seagate Exos X18 (RAIDZ2) |
| Cache VDEV | 2 × 1 TB SATA SSD (mirrored L2ARC + SLOG) |
| NIC | 10GbE SFP+ (Intel X550-T1) |
| Case | Fractal Design Define R5 (8-bay hotswap cage added) |
| PSU | Seasonic Focus GX-650 (80+ Gold) |
03. How It Was Built
Storage pool design
Six drives in RAIDZ2 gives the equivalent of four drives of usable space while tolerating two simultaneous failures. With 16 TB drives that works out to roughly 64 raw usable TB. After ZFS overhead and formatting, the pool presents ~58 TB. I carved the remaining ~14 TB into a separate mirrored pool for VM disk images and swap — workloads that need lower latency and suffer more from the write penalty of wide RAIDZ stripes.
Cache and SLOG
The two SATA SSDs serve dual roles: one is set as a ZFS Intent Log (SLOG) to absorb synchronous write bursts, and together they form a mirrored Level 2 Adaptive Replacement Cache (L2ARC) that caches frequently-read blocks. The 10GbE NIC would saturate spinning drives on sequential reads without it.
Snapshots and offsite backup
TrueNAS handles scheduled ZFS snapshots natively — hourly for the last 24 hours,
daily for 30 days, weekly for 12 weeks. Offsite backups run via a Python script
that uses rclone to sync changed snapshots to a
Backblaze B2 bucket over the S3 API. The B2 bucket has Object Lock enabled to
make ransomware deletion harder.
Container workloads
TrueNAS Scale uses Kubernetes under the hood for its app ecosystem. I run Plex Media Server (leveraging the iGPU for hardware transcoding), Nextcloud for file sync and calendar, and a private Docker registry for homelab container images. Each app gets its own dataset with dedicated quotas to prevent any single workload from filling the pool.
04. Lessons Learned
- → ECC RAM is non-negotiable for ZFS — silent data corruption is a real risk on consumer non-ECC systems.
- → RAIDZ is not a backup. The offsite B2 replication was non-trivial to set up correctly but is the actual protection layer.
- → Drive burn-in testing with badblocks before adding drives to the pool caught two early failures that would have been silent.
- → 10GbE is worth it if you're doing anything with large sequential reads; even SMB over 1GbE saturates quickly with Plex streams.
05. What's Next
The main outstanding item is migrating the containerised apps from TrueNAS's built-in K3s to the separate Pi cluster, so the NAS can be rebooted for maintenance without taking services offline. I'm also exploring a 25GbE upgrade for the NAS-to-switch uplink once the cluster migration is complete.