1. The Origin Story
It started, as most homelabs do, with a much smaller plan. I just wanted a place to dump my Blu-ray rips so I could stop hunting through external drives whenever I wanted to watch something. A flat SMB share would have done the job. Instead, I ended up with a 24-bay-capable chassis, two ZFS vdevs, a Cloudflare tenant, a Tailnet, and a Docker workload I now treat with the seriousness of an actual production environment.
Calling this "boredom" is generous. It was more like cumulative frustration: rising subscription prices, photo libraries scattered across phones, family files trapped in someone else's free tier, and a lingering sense that "the cloud" should not be the only option for people who can read documentation. TrueNAS SCALE turned out to be the most pragmatic way to consolidate all of that on hardware I already half-owned.
What follows is a reasonably honest tour of the box: what's in it, what works, what was a bad idea, and what I'd do differently if I were rebuilding from scratch tomorrow. None of this is sponsored, none of it is a guide, and almost all of it is recoverable from the wreckage of someone else's reddit post.
2. The Hardware at a Glance
This is not a from-scratch build. The chassis and motherboard are recycled from a former workstation, which is why some of the choices below look more "available" than "optimal." That's the homelab tax.
System Specs
Honest Notes on the Build
- The i7-8700K is genuinely overkill for a NAS workload. Where it earns its keep is transcoding and the three dozen sidecar containers that would otherwise fight over an N100.
- Memory is non-ECC. ZFS does not require ECC, and the "scrub of death" story is overblown, but I would absolutely take ECC if I were buying the platform new. I'm not, so I don't.
- There used to be a Quadro P1000 in here. TrueNAS SCALE 25.10 moved to NVIDIA's open GPU kernel modules, which depend on the GSP — a coprocessor that first appeared in Turing. Pascal doesn't have one, so the card stopped being supported. Not "too old for the driver": a specific architectural dependency introduced by a kernel-module change in a point release.
- I could have kept it. There are community builds of the legacy proprietary driver for exactly this situation. I chose not to maintain out-of-tree kernel modules against every future TrueNAS update for one 4 GB card, so I pulled it. Transcoding moved to the 8700K's integrated Quick Sync, and the local LLM containers — which were a toy at 4 GB of VRAM anyway — were shut down rather than migrated.
- The drives don't live in the ThinkCentre at all. Eight 20 TB disks sit in a JBOD enclosure I fabricated out of steel, attached over an LSI SAS3008 HBA running IT-mode firmware so ZFS addresses the disks directly. Hardware RAID in front of ZFS is worse than useless — it hides exactly the information ZFS needs to do its job.
3. Storage & Network
ZFS Pool “tank”
Pool Overview
Vdev Configuration
How this pool came to be RAID-Z2
An earlier version of this post argued that the pool's original layout — two RAID-Z1 vdevs, one of them 20 TB drives — was the single decision most likely to bite me. With disks that large, a single failure forces a multi-day resilver during which the survivors get hammered, and a second failure in that window takes everything. I wrote that RAID-Z2 was the textbook answer and that I'd run it if I bought the set again.
So I did. The pool you're reading about is that rebuild.
The important detail is that it could not be done gradually. ZFS cannot convert a RAID-Z1 vdev to RAID-Z2, cannot merge two vdevs into one wider vdev, and cannot remove a raidz vdev from a pool. Replacing disks in place would have grown capacity while preserving the exact topology I was trying to escape. The only route to one 8-wide RAID-Z2 was to destroy the pool and build it again.
Which meant deciding, concretely, what was worth carrying across. Photos and configuration got backed up. The media library did not — it's the one category I can rebuild, so it's the one category I let go. That's the same classification I'd written down months earlier as a principle; this is the week it cost me something.
No SLOG, no L2ARC — on purpose
There are no cache or log devices attached to this pool, and for this workload that's the correct answer rather than an omission. A SLOG only accelerates synchronous writes — NFS with sync on, databases, iSCSI configured for sync. Almost everything this box does is SMB and async writes from containers, none of which would ever touch it. An L2ARC helps repeated random reads, but its index lives in ARC, so adding one to a memory-constrained system can actively make things worse. Neither device is a "make ZFS faster" button, and buying one to look thorough is how you end up with an SSD that does nothing.
The one workload here that would benefit is the 1 TB zvol exported over iSCSI. That's the honest counter-argument to the paragraph above, and it's the trade I've accepted for now.
Health as of September 2026: all eight disks ONLINE, zero read, write or checksum errors. The last full scrub took 1 day 21 hours and repaired nothing, because there was nothing to repair.
Network & Access
The network side is deliberately unglamorous: a single 2.5 GbE link into an unmanaged switch, behind an ISP-supplied router whose firewall rules I don't own. No VLANs, no LAG, no segmentation. There is exactly one interesting thing about it, and it's a bottleneck.
Eight CMR drives in RAID-Z2 will read sequentially far faster than 2.5 GbE can carry — call it 300 MB/s at the wire, against an array that comfortably beats that. So for every transfer on this network, the constraint is the NIC, not the disks. The WAN is 3 Gbps symmetric, which is also faster than the host link, meaning this machine cannot saturate its own internet connection. The upgrade path is obvious — 10 GbE and a managed switch — and I haven't taken it, because nothing I actually do here is currently limited by waiting on a file.
Two overlays, two jobs
- Tailscale handles the admin plane: SSH, the TrueNAS UI, Portainer, Dozzle, anything I don't want on the public internet. MagicDNS plus tagged ACLs means I never type an IP address and the family never sees these endpoints.
- Cloudflare Tunnels handle the public plane: the small set of services I actually want family to reach without installing a VPN client — Jellyfin, its request front-end, and Wizarr for invitations. No open ports on the router, TLS terminated at Cloudflare.
- Worth being precise, because these get conflated: zero open ports is not the same as nothing exposed. A tunnel is an outbound connection, so the router genuinely has no inbound rules — and three services are genuinely reachable from the public internet, protected by their own authentication and nothing else.
What this is not
It is not zero-trust in any formal sense. There's no SIEM, no posture checks, no per-request identity beyond what Cloudflare Access provides. It's “sensible defaults plus an overlay network,” which is roughly two orders of magnitude better than port-forwarding, and roughly two orders of magnitude less than what a real org would deploy.
4. The Services That Run the Show
TrueNAS SCALE 25.04 (Fangtooth) finally moved the Apps system from k3s to native Docker. If you came in during the Bluefin/Cobia era, this is the headline change — container management is noticeably less painful, and most of my workloads now run as straightforward Compose-style apps with bind mounts onto dedicated ZFS datasets. The migration from the old k3s charts was not seamless and required manual data moves for a couple of apps; budget time for it if you're upgrading.
Persistent data for every container lives on its own dataset under the pool, which means snapshotting, replication, and dataset-level tuning all work cleanly per-app.
Jellyfin (and Plex, for now)
Plex was the original justification for the whole box. It's being wound down: pricing and policy changes made it a poor thing to keep building against, so Jellyfin is now the server that's actually published, and Plex goes local-only shortly. Both are running simultaneously while the migration finishes. Transcoding is handled by the 8700K's integrated Quick Sync since the discrete GPU came out.
Filebrowser
File access for the household. This slot used to be Nextcloud, which I retired — it wanted a Postgres instance, a dedicated dataset and a meaningful share of the maintenance budget to deliver something I was mostly using as a file browser. So now it's a file browser. Not every service needs to be the full-fat option.
Immich
The closest thing in self-hosted-land to a real Google Photos replacement. Auto-upload from phones, CLIP-based search, face recognition, shared albums. Its machine-learning containers used to be the main justification for having a GPU at all; with the card gone the indexing passes are slower, which nobody but me has noticed.
qBittorrent, VPN-bound
The client runs inside an image with the VPN built in and a strict kill switch: if the tunnel drops, it has no network at all rather than quietly falling back to the WAN. This used to be a separate gluetun sidecar with qBittorrent joined to its network namespace — the integrated image does the same job with one fewer moving part. It is the only container here with an egress path of its own, and that's the entire point.
Sonarr / Radarr / Prowlarr / Bazarr
The standard *arr stack for library automation: indexers, metadata, subtitles, the lot. Configured to hand files off to qBittorrent and then hardlink (not copy) into the Plex library, which keeps disk usage sane and seeding intact.
Tautulli
Plex analytics — who watched what, when, on which device, and whether it had to transcode. Mostly used to confirm I'm not silently CPU-bottlenecking someone, and occasionally to settle “did you actually finish that show” arguments.
Homarr, Dozzle, Scrutiny
The observability layer, such as it is: Homarr as the dashboard, Dozzle streaming container logs, Scrutiny watching SMART data across the array. It is not a metrics stack — there's no Prometheus, no Grafana, no time-series history. What actually does the work is TrueNAS emailing me when something is wrong, which is unglamorous and has caught every real fault so far.
CDN_Captain
A retrieval-first Discord bot I built for a client's gaming community, running here in Docker rather than on a VPS because this box was already doing enough to absorb it. There used to be an Ollama and Open-WebUI pairing in this slot too; it went away with the GPU, and I didn't miss it — 4 GB of VRAM only ever made it a toy.
Cloudflared
The Cloudflare Tunnel daemon, fronting the handful of services that need public exposure. Cheaper than a static IP, safer than UPnP, and survives ISP-level CGNAT, which is the actual reason most people end up using it.
5. Lessons, Quirks & Things I Got Wrong
Snapshots aren’t backups
ZFS snapshots are excellent for “undo” and ransomware resilience, but a snapshot that lives on the same pool as the data dies with the pool. What actually leaves the box is a weekly encrypted sync of photos and configuration to cloud storage — which means my real RPO is seven days, and I’d rather write that number down than imply something continuous. Media isn’t in that bucket at all: I can re-rip a Blu-ray, I can’t re-shoot a wedding.
Cooling and acoustics
Eight spinning drives in a consumer-ish case generate real heat and real noise. My current fan curve is a compromise between “disks under 40 °C” and “not audible from the next room.” A proper rackmount chassis would solve the airflow problem and create a new acoustic problem; I’ve chosen the one I can live with.
Cables
Eight SATA data + eight SATA power, plus the breakout for the SSDs, plus front-panel headers. No reasonable amount of cable management makes the inside of this chassis attractive. I’ve stopped pretending otherwise.
The boring stuff that matters most
- Power is the weakest layer here, and I know it. There is no UPS. Eight spinning disks and an active pool are exposed to abrupt loss, and with no SLOG the sync writes that do happen land in the in-pool ZIL. Worse, the JBOD runs on its own PSU with no sequencing logic — it has to be powered up before the host, or the HBA enumerates an empty bus. So nothing here recovers from an outage unattended. If the power blips while I'm away, it stays down until I'm standing in front of it. The fix is a UPS sized for both supplies plus NUT integration, and it is the next thing I'd spend money on.
- Updates. Container images are largely pinned on the TrueNAS-managed side and tracked by Watchtower on the hand-rolled side — a split I'd tighten if this were anyone else's system. The OS itself is a different story: I opted into the Early Adopter release train and discovered it's a one-way door. Once you're running a build newer than stable, the General channel isn't selectable any more; going back means a clean install and a config restore. I'm on a beta release of TrueNAS 26 because that's where I put myself, not because I chose it release by release.
- Monitoring. Alert fatigue is real. I get email on SMART warnings, pool degradation, scrub failures, and snapshot replication failures — not on every container restart. If everything is urgent, nothing is.
- Documentation. Every non-trivial change goes into a private notes repo with the command, the reason, and a rollback. I have lost too many weekends to past-me's undocumented cleverness.
6. Roadmap & Next Steps
Stand up Prometheus + Grafana + node_exporter for proper time-series visibility. Right now I can tell you what the box is doing, but not what it was doing at 3am last Tuesday.
Deal with capacity before it deals with me. The pool is 76% full and ZFS gets meaningfully worse at allocation past about 80%, so the clock is already running on either pruning or a wider vdev.
Offload the noisy “edge” workloads (encoding, downloads) to a small low-power box, leaving the NAS to do storage and serving. Separate post on that one.
Get to an actual 3-2-1. Today it’s closer to 2-2-1: the pool, plus one weekly cloud copy of the irreplaceable subset. That’s a defensible posture for a household and it is not the thing I keep claiming it is.
Put something in front of the publicly-tunnelled services besides their own login forms. Cloudflare Access is the obvious candidate and the reason I haven’t done it is friction for the non-technical people who use them, which is a reason and not an excuse.
Smooth the Immich experience for non-technical family members — mostly a UX and onboarding problem at this point, not an infrastructure one.
7. Closing Thoughts
Stripped of the hobbyist romance, this is a well-specced single-node NAS running a sensible Docker stack behind two complementary network overlays, with a storage layout that’s good enough for the data I have and one decision (Z1 on 20 TB drives) I’d undo if I had the disks to spare. It replaces a real amount of monthly subscription spend, gives the family a single place for photos and files, and has been stable enough that I forget it exists for weeks at a time.
It is not enterprise. There is no HA, no second site, no failover. If the building catches fire, the off-site backups are what matter, not the box. That’s a feature, not a bug — the point of a homelab is to be the right size for one person’s house, not a scale-model of AWS.
Would I recommend building one? Only if you genuinely enjoy the maintenance. If you don’t, pay for the subscription — it’s cheaper than your time. If you do, TrueNAS SCALE is, in 2026, the most reasonable on-ramp I’ve found.