How this site is built and served
This is a static site (Hugo) running on a small Linode Kubernetes
Engine cluster. Every push to main runs a GitHub Actions workflow
that builds the site, packages it into a container, pushes the image
to Docker Hub, and rolls out a new deployment on the cluster.
Nothing about the architecture is unique to woodard.tech — it’s a worked example of a Hugo + LKE + GitHub Actions deploy pipeline that anyone can adapt.
More than just this site
The cluster now hosts a few independent apps from a single monorepo — one top-level folder per namespace (this site, a self-hosted MCP server, and shared cluster infra). Each folder has its own path-filtered workflow, so a change to one app only redeploys that app. The site pipeline described here is the simplest of them; the others follow the same pattern with their own secrets and a least-privilege kubeconfig.
Read more
- Architecture — how traffic flows from the internet down to the pod serving the page you’re reading.
- Deployment — what happens on every push
to
main: build, push, apply, rollout. - Security — how the cluster’s API is protected while still letting CI deploy to it.
- Inside the cluster — the broader platform: compute, networking, TLS, storage, observability, and security posture.
TL;DR
git push main
│
▼
GitHub Actions runner
|
│ build Hugo → ./public
│ docker build/push → Docker/woodard-tech:latest
│ kubectl apply -f k8s.yaml
│ kubectl rollout restart deployment/woodard-tech
|
▼
LKE control plane
|
▼
Pods pull new image → serve traffic