I’ve decided to move my site from Jekyll to Hugo. I apologize to any RSS readers who just got spammed by all of my old posts. I tried to keep the dates/URLs as stable as possible!

My old website was built very much the way I used to do things when I was a teenager in the 2000’s. A “LAMP stack” (although no “P” (PHP), just static pages this time), maintained by SSH-ing into a VPS and manually changing HTML files/rsyncing from a git repo.

I decided to take the time to build this the proper way 1 using Docker (actually, Podman), Kubernetes, and now Hugo for the actual static site generation. So far, Hugo is far more pleasant to use than Jekyll, which is a giant ball of dependencies, configuration files, and Ruby. Hugo is far simpler configuration wise, and seems to be much better written. It uses the battle-tested html/template library from the Go standard library for doing templates, and hacking it to do other stuff is a breeze. It also seems to generate my (albeit simple) site much faster than Jekyll.

The Kubernetes part was pretty difficult for me, since I didn’t have a lot of experience with it. DigitalOcean, my provider, has a great page documenting how to set up a simple Nginx site that I found extremely useful though.

Something that was a real mind-bender for me, coming from the “old school” way of doing things, is dealing with replicas and the Kubernetes ingress. I had some experience with Nginx-proxy with my homelab setup, which I also thought was really clever. The short of it is, if your server is running multiple websites running in different containers, nginx-proxy is the one container exposed to the Internet that services all incoming HTTP requests. It is aware of all running containers (by talking to the Docker daemon), and automatically proxies requests based on the hostname to these other containers over its internal network.

Kubernetes works in a similar way, except instead of running the nginx-proxy Docker container, you set up an Ingress-Nginx Controller, which seems like basically the same idea, but built around Kubernetes abstractions instead. The Ingress-Nginx controller is another pod running in the cluster that routes incoming HTTP traffic to the appropriate service. I also set up another deployment for handing SSL certs (similar to “acme-companion”), which runs its own set of pods that handle provisioning new certs from LetsEncrypt. All I had to do was add some annotations to my kubespec to inform the cert-manager about which domains to provision, and it all worked great, and will renew automatically!

I’m still pretty new to all of this, so if I made any mistakes here (or botched something on the migration), please email me.


  1. Well, “proper” is subjective here. Let’s say the “modern” way. ↩︎

Posted 23 July, 2023