An over engineered blog

Hi!

I thought I’d kick off this blog with a post about itself.

Level 1: The blog

The blog itself is nothing fancy. Here’s the software stack:

AstroJS & mdx

I’m not a web developer. I dabble a bit, but it’s far from my bread and butter. I wanted something simple (ironically) that would just allow me to post and be “easy” to host. Astro seemed like a good fit: no javascript by default, but wouldn’t box me in if I decided to be fancy down the road either.

Blog posts are written in .mdx files with a simple yaml front matter. Astro’s content collections take those, builds a static page for each and that’s pretty much it!

Static Web Server

Under the hood, the built static site is served using a small container image using Static Web Server. You can’t really get much smaller than that. At the moment of writing this article, the image is 3.7 MiB. Yeah, there’s no images, but there’s also not half a gig of node_modules in there.

And that’s where most people’s definition of the blog would end.

Level 2: Building the blog

I’ve mentioned the blog is served via a container somewhere. Before throwing that image up on a server, it needs to be built, right? Just set up a small .github/workflows directory at the root of the repo, push to Github and let Github Actions build and push the image to ghcr.io. Nah.

Forgejo

With everything that is happening everywhere all the time, I’m trying to reduce my reliance on big internet services. That includes GitHub. One of the unstated goals of this blog is to have a fully privately small piece of the Internet to call mine. So that means as little external resources, compute, storage, you name it.

As such, this blog isn’t stored on GitHub, but on my own private Forgejo instance, a FOSS git forge. And that Forgejo instance is hosted on my NAS. In all honesty, private git servers aren’t that interesting. It holds data, I can clone, push, pull and all the other usual git stuff.

Woodpecker

So I can host the code on my hardware. But with just Forgejo, I’d need to build the blog on my laptop, and then push that image somewhere accessible for the server hosting the blog. But one thing I dislike more than monopolistic mega corporations is manual, repetitive tasks. So building the image, pushing it to a registry and updating the container by hand was a deal breaker.

Enter Forgejo’s partner in crime, Woodpecker. Woodpecker is a FOSS CI/CD engine. It runs on my Kubernetes cluster (that’s another post by itself). Forgejo requests workflow runs based on some trigger conditions and then Woodpecker spins up a container, processes the codebase to build the final static site and packages that with Static Web Server. The final image goes back to Forgejo, which hosts it in its own registry. End result: a ready-to-ship image, usable anywhere.

Level 3: Hosting the blog

The blog is hosted on my (previously mentioned) Kubernetes cluster, running on a pair of servers in my basement. When a new image is made available, a new container is started, goes live and then traffic is redirected to the new, updated instance. The old one is destroyed. Since it’s a static website, there’s no state, no storage to handle. Everything lives and dies with the container.

The cluster deserves its own post. Eventually.

But why?

There are multiple answers to that question and here’s some of them, in no particular order:

  • Opportunity to learn and improve my homelab (Forgejo / Woodpecker)
  • Digital independence
  • Why not?
  • Hobby masochism

But really, I just like to build stuff. Learning new things is fun. I don’t think anyone needs a better reason to do anything than just feeling like it.