Moving the blog to K8s

My blog is pretty simple, running hugo with the content stored in a git repo. My go-to stack for many years has been a full Fedora VM on Proxmox using Podman, which is pretty wasteful for a tiny static site. I’ve been playing around with K8s for nearly a year getting comfortable with it and have finally decided to move a “production workload” to K8s to encourage treating it like I treat Proxmox workloads (“internal production”) with little downtime, backups, well-understood operational processes, etc.

The details

I generally prefer to avoid using AI, but it was helpful to figure out the right init container setup to make this work with the vanilla hugo container image.

I use Kustomize where possible; here’s the deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hugo
  namespace: hugo
spec:
  selector:
    matchLabels:
      app: hugo
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: hugo
    spec:
      volumes:
        - name: content
          emptyDir: {}

      containers:
        - image: docker.io/hugomods/hugo:base
          args: ["server", "--source", "/src", "--bind", "0.0.0.0", "--baseURL", "blog.gnulinux.cc", "--appendPort=false"]
          name: hugo
          ports:
            - containerPort: 1313
              protocol: TCP
              name: http  
          volumeMounts:
            - name: content
              mountPath: /src
      restartPolicy: Always

      initContainers:
        - name: git-clone-content
          image: alpine/git
          command:
            - sh
            - -c
            - |
              set -e
              git clone http://hugo-readonly:TOKEN@ssh.gitlab.gnulinux.cc:8080/homelab/hugo.git /content
              git clone https://github.com/adityatelange/hugo-PaperMod.git /content/themes/PaperMod
          volumeMounts:
            - name: content
              mountPath: /content

Yes, the token is hardcoded in the manifest. I don’t have an ergonomic process to set up sealedsecrets (yet) and this token is quite literally a read only token to my public blog; I’m not worried about comitting it to an internal git repository.