TrueNAS Scale: When Your ZFS Pool Deserves Its Own Box
The appliance trade-off, ZFS layout, and knowing when to stop rolling your own

Contents
I ran ZFS on a general-purpose Debian box for years, hand-rolling zpool commands, writing my own snapshot cron jobs, and maintaining a Samba config by hand. It worked, and I learned a great deal doing it. Then one day I needed to rebuild that box for an unrelated reason, spent an evening reconstructing the exact dataset layout, ACLs, and share config from memory and shell history, and asked myself why I was doing storage administration as a hobby rather than as infrastructure. That’s the honest answer to “why TrueNAS Scale”: at some point your storage box graduates from a project you tinker with into a thing you simply need to work, and an appliance that tracks its own configuration earns its keep at exactly that point. Roll-your-own ZFS taught me most of what I know about vdevs, ARC sizing, and send streams, and I’d still recommend the exercise to anyone who wants to actually understand the filesystem rather than click through a wizard. It’s just that understanding and daily operation are different goals, and conflating them is how you end up doing archaeology on your own shell history at 11pm.
The reconstruction evening is worth dwelling on for a moment, because it’s the crux of the whole argument. Nothing about my hand-rolled setup was undocumented in the sense of being secret — every share, every ACL, every cron job existed because I’d typed a command at some point, and in principle I could reconstruct any of it from history and memory. In practice, “in principle” is doing a huge amount of work in that sentence. Configuration that lives only in the state of a running system, with no independent record of intent, is configuration you will eventually lose, whether to a dead boot drive, a botched upgrade, or simply forgetting which of three overlapping Samba stanzas was the one actually in effect. TrueNAS’s config database enforces that discipline by default, where a hand-rolled setup only has it if you remember to maintain your own record of intent — a well-commented Ansible playbook gets you most of the same benefit, but it requires the same ongoing discipline the appliance gives you for free. Defaults are what actually survive a stressful 2am rebuild.
The Appliance Trade-Off, Stated Honestly
TrueNAS Scale is Debian underneath, with OpenZFS, a web UI, and a configuration database that captures every pool, dataset, share, and permission you set up through it. The trade is real in both directions. You give up some of the “I can SSH in and do anything” freedom — TrueNAS actively discourages manual changes outside its UI/API because they won’t be tracked in its config database and can be silently reverted or cause drift the UI doesn’t understand. In exchange you get a system whose entire state is describable, exportable, and restorable: back up the TrueNAS config database and you can rebuild the exact same pools, shares, users, and permissions on new hardware in minutes, sidestepping an evening of archaeology through your own shell history.
The other side of the trade is hardware dedication. A general-purpose server running twelve things is one kernel panic away from all twelve being down. Dedicating a box purely to storage means the one service most likely to hold irreplaceable data (your files) doesn’t share fate, uptime, or resource contention with your reverse proxy, your Kubernetes cluster, or whatever container you spun up at 11pm without thinking hard about its memory limits. If your homelab has grown past “a few containers on a NUC” into something with actual blast radius when storage goes down, that separation earns its keep.
Where Scale Diverges From Core
TrueNAS has two lineages. Core is FreeBSD-based, jails for isolation, bhyve for VMs — the older, narrower lineage. Scale is Debian-based, uses Kubernetes (via a lightweight K3s-based app system) for its apps catalogue, and supports native Linux containers. If you’re starting fresh today, Scale is the sane default: it also supports multi-node clustering for scaling storage horizontally, which Core never did, and Linux compatibility means driver and hardware support is generally broader than FreeBSD’s.
ZFS Pool Layout: Get This Right First
The pool layout you choose at creation time is the decision that’s genuinely painful to change later, so it’s worth pausing on before you touch the UI. TrueNAS’s pool creation wizard will happily let you build something suboptimal if you don’t understand the underlying vdev maths.
A few concrete guidelines from having got this wrong before:
- Mirrors over RAIDZ for anything latency-sensitive. A pool of mirrored vdevs (effectively RAID10) rebuilds faster, degrades more gracefully, and gives better random I/O than RAIDZ, at the cost of losing half your raw capacity. For VM storage or anything with app data, mirrors are worth it.
- RAIDZ for bulk, sequential-read storage. Media libraries, backup targets — RAIDZ1/2 gives you better capacity efficiency and is fine when your workload is mostly large sequential reads rather than small random I/O.
- Never mix vdev types or wildly different vdev widths in one pool. ZFS stripes across vdevs, and it doesn’t rebalance existing data onto newly added vdevs automatically, so a pool built from mismatched pieces performs unevenly and is a headache to reason about.
Creating a pool through the UI generates the equivalent of:
| |
— except it also wires in its own dataset defaults, ashift detection, and property recording into its config database, none of which you get for free from the raw zpool create.
Datasets: Don’t Just Dump Everything in One
A pool is the storage; a dataset is where you actually apply policy. Every distinct use case deserves its own dataset, because ZFS properties — compression, record size, quota, snapshot schedule, encryption — are set per-dataset, and a single flat dataset holding everything means every property is a compromise across incompatible workloads.
| |
Separate datasets also mean separate, independently manageable snapshots — you can keep a year of daily snapshots on documents while keeping a week on media, because you don’t actually need a year of granular snapshot history for files that rarely change once written.
The mistake I see most often from people migrating off a general-purpose Linux box is treating the pool the way they treated a single ext4 volume: one big mount point, everything underneath it, permissions sorted out with directory-level ACLs afterwards. That approach works right up until you want to change one property for one workload. Turning on compression for the media library is instant and free if media already lives in its own dataset; it means an awkward, partial re-encode of everything if media is just a subdirectory of a monolithic pool-wide dataset, because ZFS properties like compression only apply going forward from the point you set them, not retroactively to existing blocks. The five minutes it takes to plan datasets around actual workloads before you start copying data in saves you from that exact kind of retroactive cleanup later.
Apps: When to Use Them, When Not To
TrueNAS Scale’s app catalogue runs containers directly against the pool’s datasets, which is genuinely convenient for storage-adjacent services — a download client, a media server, Syncthing (see Syncthing: Continuous Sync With No Cloud in the Middle) that needs direct filesystem access to the same disks serving your shares. The convenience is real: no separate compute host, no network share latency between the app and its data.
The trade-off is that you’re now running application workloads on the box you specifically dedicated to storage reliability, re-introducing some of the coupling you moved to a dedicated box to avoid. My rule of thumb: apps that primarily read and write the pool’s own data (indexers, media servers, sync tools) belong on TrueNAS. Anything with its own significant compute demands, or anything you’d rather reboot independently of your storage, belongs on a separate box talking to TrueNAS over NFS or SMB, or via Proxmox if you want full VMs alongside it.
Snapshots and Replication From the UI
TrueNAS wraps ZFS snapshots and zfs send/receive in scheduled tasks configured through the UI — Data Protection → Periodic Snapshot Tasks, and Replication Tasks for pushing those snapshots to another TrueNAS box or a generic SSH target. Under the hood this is exactly what you’d hand-build with sanoid/syncoid (covered in ZFS Replication: Off-Site Backups with send/receive), just with a scheduling UI and a retention policy editor instead of a cron file. If you already understand zfs send/receive deeply, this buys you very little beyond convenience; if you don’t, it’s a much friendlier on-ramp.
Hardware: What Actually Matters
The single most-repeated piece of ZFS advice — ECC RAM or don’t bother — deserves a more honest treatment than it usually gets. ECC protects against a specific failure mode: a bit flip in RAM corrupting data before it’s ever written to disk, which no filesystem checksum can catch because the checksum itself gets computed from the already-corrupted data in memory. This is a real risk, but it isn’t unique to ZFS; a bit flip in RAM corrupts data just as silently on ext4 or NTFS, ZFS just has the honesty to be associated with the conversation because its whole pitch is data integrity. Run ECC if the hardware and budget allow it, because catching that failure mode is genuinely valuable, but don’t let its absence talk you out of ZFS entirely — non-ECC ZFS still catches vastly more corruption than a filesystem with no checksumming at all.
Beyond ECC, the practical sizing guidance for a TrueNAS box: budget roughly 1GB of RAM per TB of storage as a loose starting point for general use (this scales down significantly if you’re not running dedup, which you almost certainly shouldn’t be on a home setup — dedup’s RAM cost is brutal relative to the space it saves). A dedicated boot device separate from the storage pool avoids the failure mode where a boot drive dying takes the whole appliance offline even though the actual data pool is completely fine; TrueNAS explicitly supports installing to a small SSD or even a mirrored pair of small SSDs for exactly this reason. And a UPS with proper shutdown integration configured through TrueNAS’s own UPS service matters more here than on a general-purpose box, because an unclean shutdown mid-write is the one scenario ZFS’s copy-on-write design can’t fully paper over if it happens to catch the pool during certain metadata operations.
Back Up the Config Database Too
It’s easy to spend all your planning effort on the pool layout and forget that the config database itself — the thing that makes rebuilds fast — is a single file that can be lost just as easily as anything else on the box. System Settings → General → Manual Config Upload/Download exports it on demand, and there’s a scheduled option too; get it landing somewhere off the TrueNAS box entirely, because a config backup that lives only on the pool it describes doesn’t help you when that pool is the thing that failed. I keep mine synced to the same off-site target that holds the replicated snapshots, so a full rebuild after a genuine disaster only needs new hardware, the config export, and however long the replication link takes to pull the data back — no memory, no shell history, no guessing at which permission bit I set eighteen months ago.
Troubleshooting
Pool import fails after a hardware move. TrueNAS ties pool state to its own middleware database as well as ZFS’s own pool metadata. If you moved disks to new hardware and the pool doesn’t show up, zpool import from the shell (accessible via the UI’s Shell) will usually find it by pool name even when the UI hasn’t picked it up yet — import there first, then let the UI catch up.
Manual shell changes vanish after reboot or update. This is deliberate behaviour — anything not recorded in TrueNAS’s config database is at risk of being reverted on the next middleware restart. If you genuinely need a persistent change outside the UI’s model, use a Init/Shutdown Script (System Settings → Advanced) so it’s at least tracked and reapplied consistently, rather than a one-off shell edit.
Apps pod stuck in a crash loop after an update. Check k3s kubectl logs via the Shell — TrueNAS’s app system is real Kubernetes underneath, so standard kubectl describe pod and kubectl logs diagnostics apply even though the UI abstracts them away. Storage class or PVC mismatches after an app update are the most common cause.
SMB shares slow from Windows clients specifically. Check the dataset’s aclmode and confirm you’re using TrueNAS’s native ACL editor rather than mixing Unix permissions and Windows ACLs on the same share — inconsistent ACL types are a frequent source of both slowness and confusing permission behaviour.
Verdict
TrueNAS Scale is worth it the moment your storage stops being a side project and starts being infrastructure other things depend on — the config database, scheduled snapshot/replication UI, and dedicated hardware all pay for themselves the first time you need to rebuild after a failure and don’t want to reconstruct your setup from memory. If you’re still experimenting, still enjoy hand-rolling zpool commands, or your storage lives happily alongside a dozen other services on one general-purpose box, stick with rolling your own ZFS — you’ll learn more, and you won’t yet feel the pain this appliance exists to solve.




