A lightweight K3s-based Kubernetes cluster, currently running version
v1.34.4+k3s1as of 25th February 2026, tailored for a personal homelab hostingHome Assistant,InfluxDB,Grafana,MQTT,UniFi Controller,Pi-hole,deCONZ, and more.
To better understand Kubernetes concepts, I wrote all deployment .yaml files myself from scratch, instead of relying on third-party Helm charts:
- Fully orchestrated Kubernetes stack built for Raspberry Pi
- Ideal for self-hosted services: Home Assistant, databases, dashboards, network management, and more
- Modular and portable — spin up the same stack at home or at a remote site
- Secure by default — TLS everywhere, Cloudflare WAF in front, fail2ban on the nodes
- Raspberry Pi enthusiasts wanting to run a production-grade homelab or website
- Home Assistant users who want persistent storage, TLS, and proper ingress
- Anyone learning Kubernetes who wants real working manifests, not toy examples
- DevOps engineers setting up a low-cost remote monitoring stack
A fully working homelab cluster with:
- 🏡 Home Assistant accessible at
https://ha.yourdomain.com - 📊 Grafana dashboards at
https://grafana.yourdomain.com - 🔒 Automatic TLS certificates via Let's Encrypt
- 📡 MQTT broker for all your IoT sensors
- 🕳️ Network-wide ad blocking via Pi-hole
- ☁️ Automatic DNS updates when your home IP changes
- 💾 All data persisted on NFS — survives pod restarts and reboots
- Kubernetes Distribution: Rancher K3s
- Load Balancer: MetalLB v0.15.3
- Ingress/Reverse Proxy: ingress-nginx v1.12.0 (replacing the default Traefik)
- TLS: cert-manager v1.19.4 + Let's Encrypt
- DNS/CDN: Cloudflare (proxy + WAF + DDNS)
- Nodes: Raspberry Pi 4 Model B — ARM64, 8GB RAM
- Operating System: Raspberry Pi OS (Bookworm) 64-bit
- Storage: Dedicated Raspberry Pi NFS server (SSD-based, 500GB)
- Backups: Automatic backups to Google Drive and GitHub
Feel free to explore, reuse, or adapt this repo for your own Kubernetes learning journey!
home-assistant— Core home automation hubinfluxdb— Time-series metrics storagegrafana— Metrics dashboardsmqtt_broker— Mosquitto MQTT brokermqtt2influx— MQTT → InfluxDB bridgegovee2mqtt— Govee BLE lights → MQTTdeconz— Zigbee gateway (ConBee II)pihole— Network-wide ad/DNS blockingunifi— Ubiquiti UniFi Controllercloudflare-dns— Cloudflare DDNS CronJobingress— ingress-nginx + cert-manager ClusterIssuermetallb— Bare-metal load balancer configpv_nfs— NFS persistent volume provisionerwordpress— WordPress + MariaDBingress-nginx— Cloudflare real IP forwarding config for ingress-nginx
Edit /boot/firmware/cmdline.txt (Bookworm) or /boot/cmdline.txt (Bullseye) and append to the single existing line:
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
Then install k3s with Traefik and the built-in service LB disabled:
curl -sfL https://get.k3s.io | sh -s - --disable=traefik --disable=servicelb --write-kubeconfig-mode 644
Follow this tutorial to configure your Pi as an NFS server: https://pimylifeup.com/raspberry-pi-nfs/
Then deploy the NFS provisioner in k3s:
cd pv_nfs
kubectl apply -f class.yaml
kubectl apply -f rbac.yaml
kubectl apply -f deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml
cd metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml
vi config.yaml # edit and set the IP address range reserved on your DHCP server
kubectl apply -f config.yaml
Below will install cert-manager v1.19.4, which is the latest version as of 25th February 2026.
cd ingress
kubectl create namespace cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.4/cert-manager.yaml
vi letsencrypt.yaml # update your email address
kubectl apply -f letsencrypt.yaml
Remember to open ports 80 and 443 on your router and forward traffic to the MetalLB ingress IP.
For each app, edit pv.yaml to set your NFS server IP and path, edit secrets.yaml to set credentials, then:
kubectl apply -f pv.yaml
kubectl apply -f secrets.yaml
kubectl apply -f deployment.yaml
kubectl apply -f svc.yaml
kubectl apply -f ingress.yaml # if applicable
See each app's README.md for specific instructions.
Each app has a secrets.yaml file excluded from git via .gitignore. Never commit real credentials. See each app folder for the specific secrets required.
All services are exposed via Cloudflare-proxied subdomains. DNS records are kept in sync automatically via the cloudflare-dns CronJob which runs every 20 minutes.
curl -sfL https://get.k3s.io | sh -s - --disable=traefik --disable=servicelb --write-kubeconfig-mode 644
kubectl get nodes
Always check the k3s release notes before upgrading.
Built with ☕ and mild obsession by Andrew Morty 🏴