Smart home on K3s
Self-hosted home automation
Single-node Kubernetes cluster on a Raspberry Pi 5. Home Assistant, ArgoCD, Prometheus and Grafana, all GitOps-reconciled. Twenty-plus lights, plugs and sensors. Zero ports exposed to the internet.
The same discipline, in miniature
Most smart-home setups end up as a pile of vendor apps tied together with cloud accounts. That works until a vendor goes away, or you realise your motion sensor is reporting to a server in another country.
I wanted the opposite: everything local, and every change to it in version control. Prometheus scrapes the lot. It's the same shape as the platform I run at work, sized to a flat.
One Raspberry Pi 5, K3s, ArgoCD, and a Zigbee dongle. The bill of materials fits on a postcard.
One Pi, no cloud
A Raspberry Pi 5 (8GB) is the whole control plane. I run NVMe over USB because SD cards die under sustained writes, and a UPS on the power side because Home Assistant restarting at 3am after a tripped fuse isn't an experience I wanted twice. Hardwired ethernet, because Wi-Fi isn't a network.
A SONOFF Zigbee USB coordinator handles the radio. Devices pair directly with Zigbee2MQTT, which talks to Home Assistant over MQTT. No bridges, no cloud round-trip. Bulb to coordinator to broker to automation in single-digit milliseconds.
I'm at twenty-plus endpoints today: Hue bulbs, Innr plugs on power-monitored circuits, temperature and humidity sensors, motion and contact sensors, and a solar-powered camera. Every one of them reports to Prometheus.
Where a light switch press actually goes
The claim this whole build rests on. Same press, two topologies.
Every hop is on hardware in the flat. The internet connection can drop and the lights still work, because nothing on this path needed it. Remote access is a separate concern, handled by Tailscale rather than by opening a port.
GitOps for the living room
Everything on the Pi is a Kubernetes deployment, reconciled by ArgoCD from a git repo. Adding a new automation, tweaking a Grafana dashboard, bumping the Home Assistant version. All of it goes through a commit. The cluster pulls; nothing pushes.
That sounds like overkill for a home lab, and it would be if it were any other tool. ArgoCD on K3s is genuinely 80MB of memory and a few CRDs. The payoff is a setup that survives me. If I blat the SD card tomorrow, a fresh install plus argocd app sync brings everything back.
$ kubectl get applications -n argocd NAME SYNC STATUS HEALTH STATUS home-assistant Synced Healthy zigbee2mqtt Synced Healthy mosquitto Synced Healthy prometheus Synced Healthy grafana Synced Healthy node-exporter Synced Healthy
Power draw and humidity, in Grafana
Prometheus scrapes metrics from Home Assistant's exporter and from node-exporter on the Pi itself. Innr smart plugs report real-time power draw on the kitchen heater and the hallway lamp. SONOFF LCD sensors report temperature and humidity per room.
Grafana sits on top, with dashboards for power draw and room-by-room temperature. It's a small platform monitoring stack in every way that matters; the targets just happen to be bulbs and a kettle.
Tailscale, not port-forwarding
Zero ports exposed to the internet. Remote access goes through Tailscale. Every device on my account joins a private overlay network and reaches the Pi by its tailnet IP. Nothing on the router needs opening.
The blast radius if Home Assistant is compromised is limited to the LAN, and the LAN is segmented so the IoT VLAN can't reach anything else. Boring threat-model, boring controls. That's the point.
Why it's built this way
Local-first by default
No vendor cloud, and no remote kill-switch someone else holds. If my internet goes down the lights still work. That one constraint picked most of the devices and the network topology for me.
Treat it like work
Same git, same ArgoCD, same Prometheus. The cost of applying real discipline to a home lab is small. The cost of not doing it is a fragile pile of config that nobody, me included, wants to debug at the weekend.
Right-sized infrastructure
K3s and ArgoCD aren't heavy. The whole control plane plus every workload runs comfortably on a single Pi 5 with room to spare. The temptation to add a second node for "HA" is a trap. For a flat, the right number of nodes is one.
Where this might go
Smart TRV radiator valves are next, which would let me schedule heating per room instead of per house. After that, presence detection that's good enough to stop relying on motion sensors. They're fine for "is someone in the hallway" and bad for "is anyone home".
The longer arc is local LLM integration: a small model on a separate node, so voice control and natural-language automation don't round-trip to a cloud API. Same instinct as the rest of the system. Local data, countable dependencies.
What it adds up to
K3s + ArgoCD + Prometheus
lights, plugs and sensors
GitOps-reconciled apps
ports exposed to the internet
What I actually get out of it: the house runs on kit I own and config I can read, and nothing in it phones home. When something breaks, I debug it the way I'd debug anything at work, and it stays fixed.