1,221 commits and a pipeline that did not exist: three months of the fleet

Between 22 June and 22 September 2026 the repositories behind this site took 1,221 commits and 534 merged pull requests. At the start of that window there was no continuous integration at all: a change reached a host when someone typed nixos-rebuild switch and watched the terminal. At the end of it, thirteen workflow files — roughly 5,700 lines — stand between a commit and a live host, and every deploy either passes a health gate or rolls itself back.

This is what those three months produced on the fleet and on the VPN product, and, in the middle of it, the week the commit log changed hands.

There is one non-technical reason the pace was possible, and it deserves to be on the record: I am single and I do not have a life. The fleet has me instead. Whatever is left over goes to the commit messages.

100 200 300 8 Jun 22 117 Jul 06 57 Jul 13 25 Jul 20 55 Jul 27 16 Aug 03 89 Aug 10 99 Aug 17 96 Aug 24 56 Aug 31 242 Sep 07 341 Sep 14 20 Sep 21 own git user — Aug 29 human agent

Every non-merge commit across the four repositories, by ISO week. Bars are split by the identity that authored the commit. The amber line is 29 August 2026.

The numbers

   
Non-merge commits, 22 Jun – 22 Sep 1,221
Authored under the agent identity 692 (57%)
Pull requests merged 534
Workflow files at the start / end of the window 0 / 13
Hosts described by one configuration repository 4

The single largest repository, the one that declares the hosts themselves, carried 950 of those commits and 410 of those merges.

What the fleet is

Four machines — a public edge, a mail host, a management host, and a GPU workstation — are described in one Nix flake. Nothing on them is configured by hand: the packages, the systemd units, the firewall, the WireGuard and AmneziaWG peers, the DNS resolvers, the monitoring stack and the backups are all evaluated from files in hosts/ and modules/. A host is reproducible from the repository, and the deploy path is the only path a change takes to get there — there is no ssh-and-edit step in the workflow, which is exactly what made the next three months possible at the pace they happened.

June and July — making the network declarative

The early part of the window is infrastructure work that mostly does not show up in a screenshot: the mesh itself, the WireGuard/AmneziaWG module and its peer management, DNS resolution, the backup and scrub timers, and the split between what a host declares publicly and what it keeps. The interesting thing about this period is what it enabled rather than what it shipped — once the network was code, everything after it could be reviewed, reverted and rebuilt.

On 19 July the agent framework that now does most of the typing was added to the fleet as a flake input. That is the first commit in the window where artificial intelligence appears in this repository at all, and at that point it was infrastructure, not authorship: an input in flake.lock, nothing more.

August — monitoring, then a change of hands

August is where the fleet became observable. VictoriaMetrics and VictoriaLogs landed with Grafana over the top, dashboards and alert rules went in as files, and a status page began reporting from the same stores the dashboards read. Most of the month’s commit subjects are fixes to that stack: ingest auth, retention, alert routing, panels that queried the wrong labels. That is what building observability looks like in a commit log — a long tail of small corrections until the graphs settle.

Then the last week of August does something obvious in the chart above. On 29 August the agent got its own git identity, and the commits that identity signed first are not experiments: the CI itself.

The pipeline that did not exist

At the start of this window there were zero workflow files in the fleet repository. There is no gentler way to say it than that deploys were manual and the only test was someone watching.

Commit 073ce12 on 29 August changed that in a single step — feat(ci): Forgejo Actions CI/CD — per-host deploy runners, build gate, alerting — and added the build gate and the deploy workflow at once. The same day, 1b0a065 added a secret scan so that a credential cannot reach the branch in the first place. What followed is a pipeline that grew in public, one workflow at a time:

Date What landed
29 Aug Build gate + per-host deploy runners + gitleaks secret scan
5 Sep Weekly flake input update, and alerting on every CI failure path
16 Sep Pull-request base guard — block on conflicts, warn on base drift

The deploy workflow is now 2,321 lines. It is not long because it is complicated; it is long because it refuses to guess. Before switching a host it records a baseline of the long-running enabled units, then re-checks that baseline — and every critical service — once a second, up to ten times, passing the moment all of them are active rather than waiting out a fixed sleep, and rolls the host back if a unit that was running stopped, if a critical service is not active, or if a unit disappeared that the host did not declare as retired. Each host gets its own job, so the deploy of one is not the deploy of all.

Alongside it, the product repositories got their own pipelines: the client service builds, tests and deploys itself; the private repository runs a secret scan, a host-scoped evaluation and a lock-bumping deploy chain; and this site runs a build-and-test gate, a staging deploy, a promote step, and an ephemeral per-pull-request preview — the same machinery a normal software team would expect, on hardware the same team owns.

There is a supply-chain rule in the weekly update job worth naming, because it is the kind of decision that is easy to make once and hard to keep: every flake input is frozen to a commit at least five days old before it is proposed.

That default is not a wall, though. Freezing each input independently can produce a set that contradicts itself: one input resolves to a snapshot that has already removed a builder another input in the same set still calls. When a set like that refuses to eval or build, the window is loosened one day at a time — five days, then four, then three — re-frozen and re-tested at every rung, with the absolute-latest fallback held back as a last resort at the floor. A loosened window is disclosed in the pull request rather than going through quietly. A job that cannot be talked into absolute latest is a job worth having.

September — the product layer

September is where the fleet turned into something customers touch.

The client-facing service went from an interface to a deployed Go binary, database and routes, and then grew the parts a VPN product actually needs: a provisioning path, per-tier configuration, an upload/download fair-share shaper so no single peer can starve the rest, live per-peer telemetry, and a portal that ties it together. The WireGuard tiers were split so that the management plane and the data plane are not the same surface.

In the same month we published the things that are meant to be read: a logging policy, a privacy page and terms; an audit page generated at build time from signed host reports rather than prose; and an information-security management system whose documents live in the repository, where they can be reviewed like anything else. A no-log design was implemented at the level of the storage layer — counters that could be attributed to a single device were moved to a 30-day retention, per-peer read paths were removed from the admin surface, and mail submission moved inside the mesh so that handoff no longer leaves the network.

Backups moved to encrypted off-site object storage with a documented recovery runbook. A Kanboard instance, a Matrix homeserver, and the monitoring that watches all of it were deployed the same way everything else is: as files, through the pipeline, behind the health gate.

Where the machine-drafted work started

This is the part of the log that is genuinely unusual, so it is worth being precise about rather than sentimental.

The repository does not record which commits were drafted by a model, and no commit message says so. But commit style is a fingerprint. From the beginning of the window until the third week of July, every commit subject is written the way a person writes when nobody is watching: lowercase, abbreviated, terse. Then, in the week of 20 July, the shape changes.

0% 50% 100% sustained from the week of Aug 10 0% Jul 06 n=117 0% Jul 13 n=57 56% Jul 20 n=25 31% Jul 27 n=55 6% Aug 03 n=16 79% Aug 10 n=89 79% Aug 17 n=99 88% Aug 24 n=49

Share of weekly commits authored under the human's own identity whose subject uses the conventional-commit form (type(scope):). Weekly commit counts are shown as n=.

The conventional-commit form appears at 0% through July, then jumps in the week of 20 July — the same week the site’s deploy pipeline and the reverse proxy were reworked — and settles at roughly 80% from the week of 10 August onward. That is the tell: the commit message changed shape weeks before the commit author did. Machine-drafted work written under a human identity looks exactly like that.

Four dates mark the transition:

  1. 19 July — the agent framework arrives as a flake input. Infrastructure, not authorship.
  2. 26 July — the first commits whose subjects use the conventional form land, under the human’s own git identity. Nobody is announced; the drafting style simply changes.
  3. 10 August — conventional-form subjects become the norm rather than a burst: 79% of that week’s commits, then 79% again the next week, then 88%. The author is still the human account.
  4. 29 August — the agent gets its own git identity. That week the split is 49% agent; the following weeks are 89%, 98%, 99%, 100%.

By September the fleet is being operated by an agent that opens pull requests against the same gates a person would have to pass, reads the failing job’s log when CI goes red, pushes a fresh branch, and merges only when the base-guard check says the branch is still mergeable. The 57% figure at the top of this post is a three-month average; the current rate is near total.

Think zen garden, not herd

The pipeline gets more of this post than the features do, and the reason is a background in systems engineering rather than in software. A production line is not a pile of machines; it is a set of controls, checkpoints and fail-safes arranged around a flow, designed so that an operator’s attention is spent on the exceptions and not on the routine. Years of that, plus rather a lot of Factorio and Satisfactory, leave you unable to look at a deployment process and see anything other than a line — one that is either balanced and instrumented, or being held together by hand.

So the fleet is built as a production line for configuration. Every input is inspected before it is admitted: flake inputs frozen to at least five days old, a window that loosens a day at a time rather than jumping to latest, a secret scan run before a branch can merge. Every unit is tested before it ships: the build gate, the staging deploy, the ephemeral per-pull-request preview. Every station has a checkpoint: the units that must be active before the switch is called good, and the baseline of long-running units. And nothing moves without a way back: the automatic rollback, the revert, the pinned revision. None of it is clever. All of it is deliberate.

The goal was never speed. It was set and forget — a stack this size (four hosts, a mesh, mail, monitoring, a client service, a portal, an audit pipeline) should be something you can walk away from, and the difference between a stack you can walk away from and one you cannot is almost entirely the quality of the line underneath it. Herding a behemoth by hand, every week, is exhausting and unreliable. Building the line so that the behemoth manages itself is calm, uniform and controlled — and it is the reason a three-month window like this one contains 1,221 commits instead of 1,221 incidents.

It is worth stating plainly, because the arcs above read like the output of a team: this is one person and one agent. The breadth is the point. A specialist goes deep in a narrow seam and can treat the rest of the line as someone else’s problem; a generalist has to hold the whole thing at once — the mesh, the mail path, the identity of the commit log, the retention periods, and the pipeline that ships all of it. That combination is rarer than it ought to be, and it is what makes a stack of this size tractable at a headcount of one.

Understanding every level of it — from the kernel up through the mesh, the services and the delivery line — and running the whole thing alone, without outside help, is a rarer combination than it should be. It is also one the industry is famously bad at noticing. That is its loss, not the line’s.

What this post does not claim

It does not claim the model is doing the thinking alone. The architecture, the decisions about what a VPN product should refuse to do, and the review of every change are the human’s — and the commit log shows it: the human identity still appears every week, opening and merging, and the corrections in the log are frequent enough to be a feature. What changed is who does the typing, and how much of the work survives the gates.

It also does not claim that volume is quality. 1,221 commits is a measure of throughput, not of correctness, and a fleet that could not be rebuilt from its repository would make the number meaningless. That is why the elastic measure in this post is not the commit count but the pipeline: thirteen workflows that decide whether any of those commits is allowed to reach a host.

What you can check

󰔟 Running the same kind of stack?
The tunnel this site is written from is the one I sell: WireGuard to a gateway in Montréal, three DNS postures, one price — and the same "check it yourself" habit as everything above.
[ CREATE ACCOUNT ] [ WHAT IS THE VPN ]
󰣨 ymrtech@ymrtech | 󰌠 NixOS | 󰍢 UTF-8