cd /projects
Active TrueNASZFSLinuxDockerNetworking

Homelab NAS Server

72 TB of redundant storage on TrueNAS Scale with ZFS

Homelab NAS Server cover

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.