My home Kubernetes cluster, managed as code. This repo is the single source of truth for everything running on it — bare-metal Talos Linux, reconciled by Flux, with secrets encrypted in git via SOPS.
It's public because there's no reason not to, but it's 100% specific to my setup — hostnames, VLANs, IP scheme, and hardware are all real. It started life as a fork of onedr0p/cluster-template and has diverged substantially since. Borrow freely; nothing here is meant to be a drop-in template.
| Role | Hardware | Specs |
|---|---|---|
| Cluster nodes (3×) | HP EliteDesk 705 G4 mini | Ryzen 5 2400GE · 64 GB RAM · 1 TB NVMe (WD_BLACK SN770) · 1 GbE + 2.5 GbE |
| PVE nodes (3×) | HP EliteDesk 800 G3 mini | Intel i5-6500T · 32 GB RAM · 1 TB WD_BLACK SN770 NVMe · 1 GbE + PCIe Realtek RTL8125 2.5 GbE |
| AI compute (2×) | NVIDIA DGX Spark | GB10 · 128 GB unified memory · 4 TB NVMe · 10 GbE + ConnectX-7 direct fabric |
| NAS / bulk storage | Synology DS1821+ | Ryzen V1500B · 6× 14 TB Exos X16 · 32 GB RAM · 2× SFP+ |
Three combined control-plane + worker nodes (HA etcd, allowSchedulingOnControlPlanes).
An independent three-node Proxmox virtualization cluster named pve-sbx runs on the HP EliteDesk 800 G3 hosts. See the PVE operator documentation and detailed design and acceptance plan.
| Layer | Choice |
|---|---|
| OS | Talos Linux (immutable, API-driven) |
| GitOps | Flux — main is reconciled live via a GitHub webhook |
| CNI | Cilium with kube-proxy replacement + BGP control plane (peers UniFi; no MetalLB) |
| Ingress | Traefik (Gateway API) — split admin / services / public gateways |
| DNS | k8s-gateway (split-horizon for home.kelch.io) + Cloudflare (external) |
| Certificates | cert-manager, Let's Encrypt DNS-01 wildcard |
| Block storage | Longhorn on NVMe, replica traffic on a dedicated 2.5 GbE storage VLAN |
| Bulk storage | NFS from the Synology via csi-driver-nfs |
| Databases | CloudNative-PG |
| Secrets | SOPS + age |
| Identity / SSO | Kanidm (OIDC) via the kaniop operator |
| Dependency updates | Renovate |
Workloads are organised one namespace per concern under kubernetes/apps/:
media— the *arr suite (Sonarr, Radarr, Lidarr, Bazarr, Prowlarr), download clients (qBittorrent, SABnzbd), helpers (Unpackerr, Recyclarr, Flaresolverr) and Jellyfin, all fed off the Synology over NFS with per-app NAS identity and NFSv4 ACL isolation.identity— Kanidm as the OIDC provider / user directory, run by the kaniop operator.observability— Grafana defaults to VictoriaMetrics; vmalert and VMAlertmanager own Pushover delivery, and VictoriaLogs is the surviving log backend. OpenObserve is retired, while KPS and Loki remain briefly as Git-revert rollback components under the completed bake-off decision.ai— MCPHub as a file-backed MCP gateway with capability groups and workload-scoped bearer keys, fronting nine backend MCP servers. MetaMCP and MarkItDown are retired. See the MCPHub guide.network,cert-manager,longhorn-system,cnpg-system,kube-system— the platform plumbing the above sits on.
home-lab/
├── talos/ # Talos machine config (talhelper input + per-node patches)
├── kubernetes/
│ ├── flux/ # Flux bootstrap / cluster entrypoint
│ ├── apps/ # workloads + cluster infra, one dir per namespace
│ └── components/ # shared Kustomize components (e.g. SOPS secrets)
├── bootstrap/ # Helmfile used to bring up Cilium/Flux before GitOps takes over
├── network/unifi/ # versioned UniFi-side artifacts (FRR/BGP, firewall intent)
├── devices/ # manually applied config for appliances outside Kubernetes
├── proxmox/ # PVE operator docs and deliberately applied host baseline
├── synology/ # manually applied Compose workloads on the Synology NAS
├── scripts/ # helper scripts (CI checks, bootstrap, operator helpers)
├── tools/ # benchmarks, smoke tests, migrations, manual re-import assets
└── docs/ # architecture, runbooks, plans, decision records
Start with the docs index. Highlights:
- Infrastructure architecture — network/VLAN design, the IP-addressing scheme, BGP, and storage. The reference for why things are laid out the way they are.
- PVE operations — the live independent virtualization cluster, routine checks, shared storage, backups, restore drills, and remaining commissioning gates.
- PVE cluster plan — the design rationale, IPs, storage, backups, updates, and rollout gates.
- Roadmap — forward-looking work and deferred decisions.
- Runbooks — operational procedures (Longhorn restore, Kanidm recovery, storage-network cutover, …).
- Plans and decision records (storage benchmarks, observability bake-off).
Tooling is pinned with mise; common tasks run through
Taskfile.yaml. A few I reach for often:
task reconcile # force Flux to pull the latest git state
task talos:apply-node IP=10.32.30.11 MODE=auto # push updated Talos config to a node
task talos:upgrade-node IP=10.32.30.11 # upgrade Talos on a node
task talos:upgrade-k8s # upgrade KubernetesDay-to-day Flux/Kubernetes debugging:
flux get ks -A && flux get hr -A # are reconciliations healthy?
kubectl -n <namespace> get pods -o wide
kubectl -n <namespace> logs <pod> -fBuilt on the shoulders of onedr0p/cluster-template and the wider Home Operations community. Licensed under MIT.