So, a whole 2 weeks ago I wrote about getting my homelab into git and learning to like pre-commit hooks. The promise at the end of that post was that more was coming: Kubernetes, a real GitOps loop, maybe some monitoring.
It took longer than I thought it would. Not because any single thing was hard, but because there were a lot of small things in a row, each of which had to be done before the next made sense. This is the post I wish I’d been able to read before I started.

I’m splitting this into four parts because trying to fit it in one post produced something nobody, least of all future-me, was going to read.
The series
From TrueNAS to Kubernetes: why, and picking the stack Why bother with Kubernetes at home. Why Proxmox over bare-metal Talos. Why Talos over a generic Linux + k3s. The first cluster that came up, and the one that came up correctly a week later.
Flux v2 and SOPS: making git the source of truth Bootstrapping Flux CD, the bits of GitOps that only make sense once you’ve done them, encrypting secrets with SOPS + age, and the safety net I built so I can never push a plaintext secret.
The Tailscale saga The part of the journey where I lost the most hours. The Talos
tailscaleextension, the tag split that took two attempts to get right, the kubeletnodeIPproblem that nuked Flux, thedemocratic-csicontroller that couldn’t talk to TrueNAS, and the Immich migration that fell out of the same ACL rework.Finally, Grafana The actual payoff. Helm-released kube-prometheus-stack, Tailscale
Ingressfor nice URLs, NFS-backed persistence so dashboards survive a pod restart. A short post — by the time I got here the hard work was already done.
TL;DR for impatient future-me
If you’re standing where I was three months ago: a TrueNAS box with Dockge stacks and a vague feeling that you want “real” infrastructure, here’s what I’d do differently:
- Don’t put Kubernetes on the TrueNAS host. Use a separate Proxmox box, even a small one. Mixing storage and compute makes every reboot scarier than it needs to be.
- Talos Linux is genuinely worth the learning curve. No SSH, no package manager, no shell to get wrong. Everything is a YAML patch. It’s GitOps for the OS itself.
- Pick your Tailscale tags before you start writing manifests. Splitting
tag:k8s(operator-exposed Services) fromtag:k8s-node(the nodes themselves) is the thing I most wish someone had told me. So is moving TrueNAS to its owntag:truenasrather than owning it with a user account. - Encrypt secrets from day one. SOPS
- age takes fifteen minutes to set up and means you never have to do the “shall I really commit this” dance. Add a pre-commit hook that refuses to commit anything ending
.sops.yamlwithout asops:block — gitleaks won’t catch a missing-encryption case on its own.
- age takes fifteen minutes to set up and means you never have to do the “shall I really commit this” dance. Add a pre-commit hook that refuses to commit anything ending
What this isn’t
It isn’t a tutorial. The Talos docs, the Flux docs, and the Tailscale Kubernetes Operator docs are all genuinely good and I’m not going to repeat them here. What it is is the gap between those docs: the decisions, the wrong turns, the “obvious in retrospect” stumbling blocks that won’t show up in any quickstart.
It also isn’t finished. The list of “next things” at the bottom of the README is still longer than the list of done things. But the hard part, getting from “I have a NAS with some containers on it” to “I have a real GitOps loop with monitoring, encrypted secrets, and a sensible secure-by-default network model”, is done, and that turns out to be the part most of the writing is about.
Start with Part 1 if you’re reading top-to-bottom, or jump to whichever part is going wrong for you right now if you somehow found yourself here from the interwebs.