How this site works
joe-martinez.com is served from four Raspberry Pis in a 10-inch rack at my place. Here is the path a visit takes, and how a change gets from my laptop to the cluster.
A visit
Cloudflare
Edge, outside my network
DNS, HTTPS for visitors, and a cache in front of everything. If my homelab is down, Cloudflare still serves the last copy of the pages.
Home router
UniFi gateway
Forwards HTTPS to the cluster's ingress address, handed out by MetalLB.
Traefik
Kubernetes ingress, on the Pis
Routes by hostname, sends www to the bare domain, and terminates TLS with a Let's Encrypt certificate that cert-manager renews.
nginx
Two pods on different Pis
One container image holding the whole site. A disruption budget keeps one pod up while the other restarts.
The pages
Static files
Built with Astro. The 3D rack is three.js and only loads once it's on screen.
Live status
/api/status, cached 30 seconds
nginx asks the rack-display status service, which keeps a summary of the cluster.
Status service
Node.js, rack-display
Turns cluster state into the face on the rack's screen and a short public summary: node health, CPU, temperature and this site's uptime. No hostnames, IPs or app names leave it.
Prometheus and Alertmanager
kube-prometheus-stack
Fed by node-exporter on each Pi, kube-state-metrics, PoE data from the UniFi switch, the NAS, and a probe that loads this site every minute.
A change
git push
github.com/0xJMart/resume-site
Resume content lives in one YAML file. The page, the printable resume and the PDF all render from it.
GitHub Actions
CI
Type-checks and builds the site, renders the PDF and preview images in a headless browser, and pushes an arm64 image to GitHub's container registry.
Flux
GitOps, in the cluster
Spots the new image tag, commits it to my homelab repo, and applies it. Nothing is deployed by hand.
Kubernetes
k0s on four Raspberry Pi 5s
Rolls the two pods one at a time.
Uptime probe
Blackbox exporter
Loads the public URL every minute. If it fails, the rack's status face goes wide-eyed and the uptime figure on the front page drops.
The rest of the homelab runs the same way: Keycloak for single sign-on, Sealed Secrets, CloudNativePG, and an Unraid NAS for storage, all from one Git repository. Back to the rack.