← All chapters
Chapter 06 · 27 July – 16 August 2026

Cutting the Cord

This is the chapter where “migration” stops being an ongoing project and starts being a series of final, irreversible steps. Three weeks, and by the end of them almost nothing from the old world is still load-bearing.

Finishing what July started

The week opens tidying up the Longhorn rollout from the previous chapter: GitLab’s backup job was hitting OOMKills and got its memory limit raised to 4Gi (27 July), and the remaining stateful PVCs — GitLab’s Gitaly repo storage, Harbor’s job service and registry, and the SeaweedFS object store GitLab’s backups deliberately avoided — all made the same pause-migrate-resume trip onto Longhorn on 28 July.

Two real bugs surface in the days after, both worth naming because they’re the kind of thing that only shows up under real load. On 29 July, the imapsync CronWorkflow started intermittently failing its OpenBao AppRole logins — the fix was serializing the workflow so 39 accounts didn’t all try to authenticate to OpenBao in the same instant and trip its rate limiting. The same day, talos-04 and talos-06 fell into a kubelet restart loop: their Cilium Egress Gateway IPs shared the same /24 as the node’s own IP, which confused the kubelet’s NodeIPController into thinking its own address kept changing. The fix was pinning each node’s nodeIP explicitly to exclude the egress addresses.

2 August: the last VMs

2 August 2026 is the day the cluster’s own control plane stopped being partly virtual. talos-01 and talos-03 — the original VM-based, control-plane-only nodes going all the way back to the cluster’s first talconfig.yaml — were removed for good. Every control-plane node from this point on is physical, schedulable hardware.

The same day carries UniFi’s real migration — not the false start from chapter 3, this time done properly: Longhorn storage instead of NFS, a Mongo dbOwner grant fixed on the restore/backup staging databases, Mongo’s memory limit raised twice (first to some initial bump, then to 8Gi) after it got OOMKilled mid-restore, a Recreate deployment strategy adopted specifically because UniFi’s RWO PVCs deadlock under the default rolling-update strategy if the replacement pod lands on a different node, and — replacing the old VM’s own automation — a proper rclone-based sync of UniFi’s daily backup straight to the real Dropbox.com account, after an NFS-based attempt turned out not to actually replicate what the VM had been doing. A full writeup landed in the docs the same day.

The inherited Vault, switched off

4 August carries one line that closes a chapter going back to before this repository even existed: “docs: mark old Vault cluster as fully decommissioned.” The Vault cluster spread across srv2.8p.uk and cp03.abt.me, with debian-gitrunner as its original Raft leader — the exact secrets infrastructure described in the very first entry of this journey — is finally, fully torn down. Package, data, TLS material, config, and the dedicated WireGuard mesh those nodes used to reach debian-gitrunner all go with it. debian-gitrunner itself stays powered off, untouched, a museum piece rather than an active dependency.

More node churn, and a second attempt at physical growth

Node topology keeps moving through the rest of this stretch: talos-03 rejoins on 8 August as a genuinely new fifth physical node (the name reused a third time in this project’s history), surfaces a recurring Longhorn disk-creation race on join that gets documented rather than fixed outright, then is removed again on 11 August along with talos-02, settling the cluster back to the three-node shape it holds today. A second in-cluster GitLab Runner is added the same day, this one specifically registered against gitlab.com rather than the self-hosted instance.

The GitLab.com pivot

By 13 August, CI jobs start repointing at registry.abt.me, the project’s new self-hosted image registry, in place of the in-cluster one. Then, on 14 August, the whole cluster’s own CI/CD and ArgoCD source moves to gitlab.com (abtme1/talos) — the repository this very account is written from switches home mid-project.

The following day brings the migration’s most serious real incident: an accidental OpenBao root token revoke during cleanup work. Recovery took most of a day and is documented in full as its own RCA rather than glossed over. GitLab itself was paused properly that same day — scaled down through its own Helm values rather than a live kubectl scale, so the desired state in git stayed truthful — ahead of its final removal.

16 August: “Decommission in-cluster GitLab.” The instance built on 19 July, cut over on 20 July, is gone less than a month after it went live, fully superseded by gitlab.com. The cleanup wasn’t perfectly clean — a ReferenceGrant got deleted along with the rest of GitLab’s manifests that shouldn’t have been coupled to them, and notification.turnbull.uk returned 500s for several hours before the missing cross-namespace grant was spotted and restored. It’s included here rather than left out, because an honest account of a migration includes the mistakes that happened in production, not just the ones caught before they shipped.

By the end of this chapter, the picture has fully inverted from where chapter zero started: no VM carries control-plane responsibility, the inherited Vault is gone, UniFi runs properly in-cluster, and even the project’s own source of truth has moved to infrastructure outside the home lab entirely.