The Hugo, S3, CloudFront, and AI drafting pipeline behind this blog The Hugo, S3, CloudFront, and AI drafting pipeline behind this blog

How this blog is built: Hugo, S3, CloudFront, and an AI drafting pipeline

TL;DR This site is deliberately boring infrastructure for a reason: Hugo generates static HTML with the PaperMod theme. Terraform manages AWS (S3, CloudFront, Route53, ACM). GitHub Actions and self-hosted k3s runners deploy on every push to main. An AI pipeline (Bedrock + a Python script) drafts articles into Hugo page bundles and opens PRs for review. There’s no dynamic backend, no database, no server to maintain. The AWS bill is ~$30/month. This post is a tour of the machine that prints the other posts. ...

June 19, 2026 · 8 min · zolty
Parallel agents sweeping repos for improvements under a token budget Parallel agents sweeping repos for improvements under a token budget

Token-budgeted self-improvement: pointing parallel agents at my own repos

TL;DR I have $X in monthly Claude tokens I don’t always use. Instead of letting the unused credit evaporate, I built a parallel agent sweep that fans out autonomous scouts to scan for dependency upgrades, CVEs, CI waste, and quick wins across my repos. Each discovery agent returns a scored candidate list. The orchestrator triages and ranks them, then spins up isolated worktree agents to implement the safe ones — all under a hard token cap and with human gates between phases. The output is a pile of merge requests, not silent commits. Noise is real and review burden is the limiting factor, but when it lands right, an hour of agent work + human review beats a weekend of manual maintenance. ...

June 16, 2026 · 9 min · zolty
A GitLab CI pipeline using an LLM to review and fix merge requests A GitLab CI pipeline using an LLM to review and fix merge requests

LLM-powered GitLab CI: auto-reviewing and auto-fixing merge requests

TL;DR I’ve wired LLMs into my GitLab CI pipeline to auto-review merge requests, post findings as comments, and (on command) generate patches and commit fixes. The key insight: deterministic gates run first. Before the LLM ever sees a diff, regex-enforced checks block deleted tests, committed secrets, and destructive commands. Regex is certain; LLM judgment is probabilistic. Gate first, judge second. The bot reviews silently unless it finds something, posts to the MR with confidence levels, and can be leveled up from read-only observer to trusted committer as it proves itself — hence the “autonomy ladder” (Rungs 0–4) that gates who decides what. Infrastructure repos cap at Rung 2 (never auto-merge). ...

June 15, 2026 · 8 min · zolty
GitLab CE on k3s with S3 backup arrows GitLab CE on k3s with S3 backup arrows

Migrating from GitHub to self-hosted GitLab CE — and rebuilding it from S3

TL;DR I moved every private homelab repo off GitHub onto a self-hosted GitLab CE 18.10 instance running on my k3s cluster. GitHub stays as a read-only mirror plus the break-glass k3s_bootstrap repo. Two weeks later I accidentally blkdiscard’d the GitLab volume and rebuilt the entire instance from an S3 backup. It worked, but the boring parts — runner re-registration, group tokens, container-registry pull secrets — were the real cost. Why bother GitHub was fine. GitHub Actions was fine. The thing that pushed me over was billing math plus blast radius: ...

April 29, 2026 · 5 min · zolty
Self-hosted GitHub Actions cache server Self-hosted GitHub Actions cache server

Self-Hosting a GitHub Actions Cache Server on NAS Storage

TL;DR If you run self-hosted GitHub Actions runners, every actions/cache step is round-tripping to GitHub’s cloud storage. For a homelab cluster with local runners, that means cache restores travel from GitHub’s CDN to your runner, through your ISP, and back – even though the runner is 10 feet from your NAS. I deployed falcondev-oss/github-actions-cache-server as a Kubernetes deployment, pointed it at NFS storage on my NAS, set one environment variable on my runners, and flushed all the GitHub-hosted caches. Zero workflow changes required. ...

March 27, 2026 · 5 min · zolty
CI/CD pipeline for blog deployment on k3s CI/CD pipeline for blog deployment on k3s

This Blog Deploys Itself: Self-Hosted CI/CD on k3s with GitHub ARC

TL;DR The blog is deployed by GitHub Actions runners running inside the same k3s cluster it’s talking about. A push to main with content under hugo/ triggers a build, a two-pass S3 sync, and a CloudFront invalidation. A daily 06:00 UTC cron handles future-dated posts so I can commit a backlog and let them drip out on schedule. After every successful deploy, a Playwright job kicks off and scans the live site for broken links, visual regressions, and security header compliance. The whole thing runs on eight self-hosted amd64 runners managed by GitHub’s Actions Runner Controller (ARC) in the cluster. Not a single managed CI minute gets billed. ...

March 26, 2026 · 7 min · zolty
Harbor container registry Harbor container registry

Ditching AWS ECR for Self-Hosted Harbor: Why and How

TL;DR AWS ECR tokens expire every 12 hours. Every time the cron job that refreshes the pull secret fails, image pulls break cluster-wide. Docker Hub’s anonymous rate limit (100 pulls/6 hours) started hitting during CI builds that pull nginx:alpine and python:3.12-slim. I replaced both with self-hosted Harbor for container images and Gitea for package registries (PyPI, npm), backed by NFS on the NAS, deployed via Ansible and Helm, with Trivy vulnerability scanning on push. Thirteen CI workflows were updated in a single commit. Pull secrets never expire. Images never rate-limit. Monthly ECR cost drops to zero. ...

March 21, 2026 · 5 min · zolty

Affiliate Disclosure: Some links on this site are affiliate links (Amazon Associates, DigitalOcean referral). As an Amazon Associate, I earn from qualifying purchases. This does not affect the price you pay or my editorial independence — I only recommend products and services I personally use and trust.