2025.11.28 · TX/832 892w

Setting up my first real homelab (and the mistakes that came with it)

FIG. 01 - SETTING UP MY FIRST REAL HOMELAB PLATE 01 / 01

There’s no single moment where a few Docker containers on a NUC become a homelab. It happens by accident, in the gap between adding one more service and realising you can’t remember what’s running on which machine without checking. Mine crossed that threshold sometime in November 2025, though I didn’t notice at the time. The naming was the giveaway. Once I’d started calling the boxes by name instead of by IP, they’d become things I was responsible for rather than experiments I could throw away.

Three machines do most of the work. DIRECTIVE is the Ubuntu Docker host – Home Assistant, Open WebUI, Ollama, Piper TTS, and the small constellation of services that accumulates whenever you have somewhere to run them. MeSeekBox is the primary NAS, a UGREEN DXP4800 Plus with three 8TB drives in RAID 5, holding media, documents, and backups for the other two. EVAcore is the dedicated download box, a QNAP TS-451+ running Gluetun, qBittorrent, and the *arr stack behind a ProtonVPN tunnel, rsyncing completed jobs to MeSeekBox. The roles are clean now. They weren’t, originally.

The names are Pixar and Trek, mostly. Wall-E, EVA, M-O, and a sprinkling of Starfleet. It sounds like the sort of thing you do for fun, and it is, but there’s an honest argument underneath: a machine called homeserver1 gets homeserver1’s level of care. A machine called DIRECTIVE gets DIRECTIVE’s. The kit doesn’t actually mind what you call it, but you do. Once a box has a name, you stop treating it as disposable. You document it. You back it up. You notice when it misbehaves. I don’t think I’d have stuck with any of this if I’d left the machines as numbered placeholders.

The mistakes are where the post earns its place, because most homelab writing online is written by people whose homelabs are finished. Year one is usually edited out. Mine wasn’t tidy.

The network was wrong for too long. Everything sat on one flat subnet behind the consumer router the ISP had sent in a box, which worked, in the sense that packets went where they were supposed to most of the time. It also meant the smart-home gear, the workstation, the servers, and anything a guest connected to were all in the same broadcast domain. The Flint 2 came later than it should have, with proper subnets and a guest network. I’d known this needed doing for months by the time I actually did it.

Storage was the same kind of late. The earliest version had services writing to a single drive on the NUC, with no backup plan worth the name. MeSeekBox was retroactive scaffolding – building the storage layer after I already had things I couldn’t afford to lose. RAID 5 was the right answer in the end, but it shouldn’t have taken losing sleep over a flaky drive for me to get there.

I didn’t document anything for the first six months. Every change was made, used for a week, and then quietly forgotten. When something broke, the fix was archaeology – bash history, timestamps, trying to remember why a port was forwarded and to where. I started writing things down around month seven, which was six months too late. I still find notes about services that no longer exist, configuring things in ways I no longer use, and I have to read them carefully before deleting anything, just in case past me knew something present me has forgotten.

The VPN setup took three attempts. First go had qBittorrent on the wrong network, leaking real IPs every time the tunnel hiccupped. Second go had Gluetun on the wrong host, which fixed the leak but meant downloads stopped whenever DIRECTIVE rebooted. Third go is what’s running now – Gluetun and qBittorrent on EVAcore, *arr stack pointed at it through the tunnel, rsync to MeSeekBox once a file is complete. The third version is fine. The first two were not.

The thing nobody warns you about, or possibly the thing everyone warns you about and I didn’t listen, is that every service generates more services. A media library needs a metadata fetcher. The metadata fetcher needs a queue. The queue benefits from monitoring. The monitoring wants notifications. Each addition is small. You make the call on each one in isolation – ‘this is just one more container, it’s fine’. Then you look at the Dockge dashboard six months later and count the services and wonder when that happened.

Looking back at screenshots from those first weeks is a strange experience. The dashboards were ugly. The naming was inconsistent. There were three different ways of doing reverse proxying running at once for reasons I can no longer reconstruct. It works now, and most of it works without me having to think about it, which is the whole point of infrastructure. But year one was rubbish, and I had to redo most of it before it got to the point where it could be ignored.

The homelab is still a continuous project. New services arrive. Old ones get replaced. Something breaks every few weeks and I fix it, or I leave it broken if it wasn’t important. The point isn’t to finish. The point is to have something running that mostly behaves, that mostly stays out of the way, and that I mostly trust. Mostly is the operative word. It’s always been mostly.

00 NODE
▾ OPEN