Homelab
cat homelab/README.md
Static pages ship to Cloudflare Pages. Dynamic bits — the API proxy and analytics — still run on a private Kubernetes cluster I operate, reached only through an outbound-only tunnel.
Architecture
Visitor
Browser requesting mogra.dev
HTTPS
Cloudflare
DNS, TLS, Pages for HTML, edge Functions for a few paths
Edge routes
/*
Cloudflare Pages
Hugo static site — blog, resume, projects, this page
/api/* · /t.js
Pages Function → tunnel
Proxies to origin.mogra.dev on the cluster
outbound-only tunnel — the cluster dials out, nothing dials in
Kubernetes cluster namespaces: mogra, umami
/api/*
mogra-proxy
Go service that caches upstream API responses
upstreams
- GitHub API
- Stack Exchange API
/t.js · /api/send
umami
Self-hosted analytics
The cluster has no public IP and no inbound ports. It holds one outbound connection open to Cloudflare, and API traffic arrives back down that link. HTML never touches the cluster.
kubectl get deployments -n mogra
NAME READY UP-TO-DATE AVAILABLE mogra-proxy 1/1 1 1
How a content change ships
- git push to main
- GitHub Actions: hugo --minify
- GitHub Actions: wrangler pages deploy
- live on the edge
No laptop deploy. No container image, no registry push, no GitOps image bump for a blog post. Cluster releases still go through the infra repo when the proxy or tunnel config changes.
Components
| Component | Role |
|---|---|
| Hugo | Static site generator — blog, resume, projects |
| Cloudflare Pages | Hosts the built HTML/CSS/JS globally |
| Pages Function | Forwards /api/* and /t.js to the tunnel origin |
| Go proxy | Caches GitHub and Stack Exchange API responses |
| Umami | Self-hosted analytics behind the tunnel |
| Argo CD | GitOps — reconciles cluster workloads against infra |
| Tunnel agent | Outbound-only link, so the cluster needs no public ingress |
| Terraform | DNS, Pages project, tunnel ingress as code |
Why this split?
- Blog and content updates stay a static deploy — minutes, not a Deployment rollout
- The API proxy and analytics still run on hardware I control
- Practising what I preach on infrastructure, without making Markdown pay the container tax
- The site itself is still the portfolio piece
echo "Built with Go, Hugo, Pages, and still too much YAML"
# Built with Go, Hugo, Pages, and still too much YAML