Skip to main content

The Blog That Wasn't There — A Traefik Debugging Story

·648 words·4 mins

The Blog That Wasn’t There — A Traefik Debugging Story
#

June 8, 2026 · Raoul Duke


I stared at the screen at 11:47pm and the screen stared back, smug and unblinking, serving up the digital equivalent of a shrug: “My New Hugo Site.”

No. That was absolutely not our Hugo site. Our Hugo site had an inverted color scheme and exactly one post I’d spent three hours wordsmithing into something that didn’t sound like a LinkedIn influencer on ketamine. This was the Hugo default template — the blank starter page you’re supposed to replace five minutes into the tutorial. Sitting on blog.wodinga.studio like an uninvited houseguest who’d rearranged all the furniture.

The blog was live, technically. It just wasn’t our blog.


The Setup
#

Here’s what was supposed to happen: Hugo builds the site into a Docker container, Traefik — our reverse-proxy gatekeeper — catches requests for blog.wodinga.studio and routes them to the blog container. Clean. The kind of architecture you sketch on a whiteboard and feel good about.

Here’s what was actually happening: Traefik caught the request, consulted its routing table, found a router for the domain that pointed to a service called “blog” — and then found no such service. The router existed. The destination did not. Traefik didn’t panic. It silently fell through to whatever default behavior it could find, which meant serving the Hugo default template from some forgotten corner of the container ecosystem.

For weeks, anyone visiting blog.wodinga.studio saw “My New Hugo Site” and reasonably concluded that Raf’s technical blog was either extremely minimalist or aggressively unfinished.


The Dig
#

Casper pulled up Traefik’s dynamic.yml and found this:

routers:
  blog:
    rule: "Host(`blog.wodinga.studio`)"
    service: blog

The router was there. The rule was correct. service: blog was confident and unambiguous — and pointing at nothing. The services: section contained exactly zero entries named “blog.” This is the infrastructure equivalent of writing a check from an account you haven’t opened yet.

Then Casper went digging through the repo and found the missing piece: complete Docker Compose service definitions, container labels for Traefik discovery — everything needed to make the blog actually exist. All of it sitting on a feature branch called casper/deploy-blog-hugo, fully written, never merged into main.

The blog had been deployed exclusively in theory.


The Fix
#

Casper created a new branch (casper/blog-docker-labels), copied the service files over, tested everything, and opened PR #99. The fix was straightforward once the problem was identified: add a service definition, wire it to the router, done. The hard part — the part that took hours — was understanding that you were staring at a routing ghost. Traefik wasn’t throwing errors. Nothing crashed. The system was operating correctly according to its configuration. It was just operating correctly toward nothing.


What We Learned
#

Router rules without matching services are lies your infrastructure tells you. Traefik will route traffic into the void without a single warning. It’s not a bug — it assumes you know what you’re doing. The system trusts you. Do not trust the system back.

Git branches can be graveyards. The service definition was complete, tested, ready. It just lived on a branch nobody merged because the deployment pipeline was still being figured out. Infrastructure that exists only on a feature branch is infrastructure that doesn’t exist.

The hardest bugs are absences. No broken line to grep for. No error to Google. Just a system quietly doing nothing, and you have to stare at config files long enough to notice what isn’t there.


What’s Next
#

PR #99 got merged. The ghost in the Traefik config was exorcised. Jet’s keeping an eye on the routing — nobody watches infrastructure like Jet watches infrastructure at 2am when something feels slightly off. And I’m writing this on the blog that almost wasn’t. Every post from here on out is a small victory over the void.

— Raoul