This repository runs my home lab — a single machine in my house that hosts the apps and services my household depends on (media library, home automation, dashboards, chat, and more) instead of renting them from big cloud providers.
The twist: nothing is configured by hand. The entire setup is written down as code in this repo, and software continuously keeps the real machines matched to it. Push a change and it rolls out on its own; if the machine dies, I can rebuild it from scratch in minutes.
🤓 For the technically curious — the interesting bits
- Talos Linux — a minimal, immutable OS with no SSH or shell; the node is defined entirely from
talos/and managed over an API. It runs bare metal on my NAS, with ZFS provided by a Talos system extension. - Flux GitOps — the cluster reconciles itself to match this repo. Every change is a reviewed commit, never a manual
kubectl apply. - Cilium + BGP — pods get routable IPs and LoadBalancer services are advertised straight to my UniFi router via BGP.
- External DNS UniFi Webhook — a webhook I wrote so DNS records publish directly to UniFi, no extra resolvers.
- Renovate — container images and Helm charts stay current through automated pull requests.
- OpenEBS ZFS LocalPV — persistent volumes are ZFS datasets carved directly out of a fast NVMe pool, with bulk media on a separate HDD pool.
- Kopiur + ZFS — persistent volumes are ZFS-snapshotted and backed up off-site to Backblaze B2, with the bulk datasets (documents, projects, photo library) shipped to the same bucket on their own schedule.
Built from onedr0p's cluster template — you don't need a fancy multi-node setup to run your own (this one is a single node). Come say hi in the Home Operations Discord.
This repository uses the following layout for Kubernetes.
📁 bootstrap
├── 📝 helmfile.yaml # Helmreleases required to bootstrap Flux.
└── 📝 secrets.yaml.tpl # Secrets required to bootstrap Flux.
📁 kubernetes
├── 📁 apps # Application configurations.
└── 📁 components # Shared Kustomize components.
📁 talos
├── 📁 nodes # Per-node override configurations.
├── 📝 machineconfig.yaml.j2 # Base Talos configuration for all nodes.
└── 📝 talos.env # Kubernetes and Talos version variables.
📁 unifi # Configuration files for UniFiMost things are self-hosted, but a few critical pieces live in the cloud — to sidestep chicken-and-egg problems and stay reachable when the cluster is down.
| Service | Use | Cost |
|---|---|---|
| 1Password | Secrets with External Secrets | ~$55/yr |
| Cloudflare | Domains, Workers, Pages, and R2 | ~$240/yr |
| Backblaze B2 | Backups | $1/m |
| GitHub | Hosting this repository and continuous integration/deployments | Free |
| Let's Encrypt | Issuing SSL Certificates with Cert Manager | Free |
| Migadu | Email Hosting | ~$20/yr |
| Pushover | Kubernetes Alerts and application notifications | Free |
| UniFi Site Manager | UniFi External Access Management | Free |
| Total: ~$10/mo |
Everything runs on a UniFi stack split into VLANs for isolation. The cluster hands out service IPs from a dedicated network and advertises them to the router over BGP (see Cilium + BGP), so a load-balanced app gets a real, routable address on my LAN — no port-forwarding or ingress hacks.
flowchart LR
classDef gateway fill:#163a1e,stroke:#27ae60,color:#fff
classDef switch fill:#1e2a4a,stroke:#3498db,color:#fff
classDef compute fill:#4a1e3a,stroke:#e74c3c,color:#fff
classDef ap fill:#1e3a2a,stroke:#2ecc71,color:#fff
Internet(["The Internet"])
Internet -- "2 Gbps ↓ / 350 Mbps ↑" --> UCG["UCG Fiber (Mystic)"]:::gateway
UCG -- 2.5G --> FLEX["USW Flex 2.5G 8 PoE"]:::switch
UCG -- 2.5G --> U7XG(["U7 Pro XG (Office)"]):::ap
UCG -- 10G SFP+ --> MAX["USW Pro Max 16 PoE"]:::switch
MAX -- 10G --> PUDDLE["Puddle (TalosNAS)"]:::compute
MAX -- 1G --> U6LR(["U6-LR (Garage)"]):::ap
MAX --> PDU["USP PDU Pro"]:::switch
U7XG -. mesh .-> UDB["UDB Switch (Garage)"]:::switch
| Name | VLAN | Description |
|---|---|---|
| Management | 1 | Servers + Network Management |
| Devices | 2 | Wireless Devices and Workstations |
| IoT | 3 | Small devices that have the potential to be compromised, so they don't get to talk to each other. |
| Services | 4 | No DHCP — dedicated network for the cluster's BGP-advertised LoadBalancer IPs |
| "I Don't Trust You" | 86 | Non-affiliated organization issued devices (school or work devices) |
I wrote External DNS UniFi Webhook so External DNS can publish the cluster's service and ingress hostnames straight to UniFi's built-in DNS — no extra resolvers or moving parts.
45HomeLab HL15 · 256 GB RAM · 64 threads · Talos Linux (bare metal) · single-node Kubernetes
The same box is the NAS and the cluster: Talos runs directly on the hardware, ZFS comes from the siderolabs/zfs extension (ARC capped at 219 GiB), and OpenEBS ZFS LocalPV provisions volumes from the pools below. Intel iGPU is exposed to pods for transcoding.
- Boot — 1 × 1 TB Kingston NV3 NVMe
luddlepool — Samsung PM9A3 1.92 TB U.2 NVMe; app PVCs (openebs-zfs-luddle, default StorageClass)puddlepool — bulk storage- 6 × 12 TB Seagate IronWolf / Exos 7E8 HDD — 6-wide RAIDZ2
- 2 × 1.92 TB Samsung PM9A3 NVMe — L2ARC cache
- 2 × 750 GB Intel Optane NVMe — mirrored metadata (special) and log (SLOG)
- 1 × 12 TB Seagate IronWolf — hot spare
- UCG Fiber ("Mystic") — router · 2.5 G WAN
- USW Pro Max 16 PoE — 10 G SFP+ / PoE switch
- USW Flex 2.5G 8 PoE — 2.5 G PoE switch
- USP PDU Pro — rack PDU
- U7 Pro XG — Wi-Fi 7 AP (Office)
- U6 LR — Wi-Fi 6 AP (Garage)
- UDB Switch — workbench switch, wireless mesh (Garage)
Eaton 5PX1500RT — 1500 VA rackmount UPS
- Meshtastic MQTT Gateway — LoRa mesh → MQTT
- SMLIGHT SLZB-06M — Zigbee / Matter gateway
Thanks to all the people who donate their time to the Home Operations community.
Special thanks to: ᗪєνιη ᗷυнʟ, Bᴇʀɴᴅ Sᴄʜᴏʀɢᴇʀs, and Toboshii Nakama for their assistance.
Check out kubesearch.dev to see what other users are running in their kubernetes home labs!