In this series

  1. Why I modernized my homelab instead of upgrading it
  2. Making a homelab repository agent-friendly
  3. Building the new K3s foundation
  4. Proving the entire platform with one blog (this post)
A developer writes a blog on one side of a split workshop while its healthy page arrives through the platform delivery path on the other

One stateless blog acted as a test signal through the platform’s complete delivery path.

After building the K3s control plane, I needed to find out whether the rest of the platform actually worked. I could have moved several applications at once and spent days wondering which layer was broken. Instead, I chose the simplest workload I had: this blog.

It is stateless, quick to rebuild and very easy to recognise when it works. If you can read the page, the test passed! That made it a perfect signal for the complete path: Git → Flux → MetalLB → Traefik → cert-manager → TLS.

One small blog, one very big test

Each project had one clear job. Flux applied the desired state from Git. MetalLB gave the cluster an address on my home network. Traefik received requests, matched each hostname to the correct service and terminated TLS. cert-manager obtained certificates from Let’s Encrypt through Cloudflare DNS.

That sounds like a lot of moving parts for one little blog. That was exactly the point! A familiar page turned the whole platform into a simple yes-or-no question: did a change in Git arrive correctly over HTTPS?

The feedback loop was fast. I could make one change, let Flux apply it and check the result in the browser. There was no database to migrate and no user data to protect. The blog gave me confidence in the shared networking before I put anything more complicated behind it.

Kubernetes was healthy, but Chrome disagreed

The best example came when Kubernetes looked healthy but Chrome still rejected the TLS connection. My split DNS was combining local and upstream records for the same hostname, so the browser received two incompatible descriptions of one service. Making the local answer authoritative fixed it.

No amount of restarting pods would have helped. The platform was not healthy until I could use it from the browser. That small test checked the path I actually cared about, not merely the individual pieces inside Kubernetes.

Pave the way for beta

Once the page loaded through Traefik with a valid certificate, I had more than a working blog. I had a baseline networking path that every future application could reuse. Traefik became the front door for ingress and TLS termination instead of every application inventing its own way in.

That simple baseline later made a much safer workflow possible. An application can have a separate beta deployment with its own hostname while still using the same Traefik and TLS path as production. Local DNS points the beta hostname at the cluster, while a Traefik allow-list keeps it accessible only from my home network.

This gives me a realistic but LAN-only beta environment. I can test an application over HTTPS without exposing unfinished work to the public internet. The beta setup is more advanced, but it rests on the same path first proven by one very simple blog.

Of course, the blog did not prove data recovery or any stateful migration. It did prove that the platform had a working front door and a fast feedback loop. With that baseline in place, I was ready for the much scarier PostgreSQL migration.