The council dashboard showing a run's pipeline, all stages passed through the approval gate

The Council Gets a Front Door

The council worked. One request went to Claude, Codex and Kimi, they answered independently, and nothing touched the lab without a human approval bound to a hash of the exact plan. It also lived entirely in a terminal, which meant that to approve a run I had to type a run id like hc-20260822-6fbfa5 and then re-type the original 350-character request verbatim, because resume rebuilds the context pack from it. Get one character wrong and you have quietly changed the inputs the agents were judged on. ...

23 August 2026 · 7 min
Pipeline diagram: one context pack fans out to Claude, Codex and Kimi in a blind first round, then a peer round, then a free model synthesises, then a human approval gate, then execute and verify

Three Agents, One Approval Gate — Making Claude, Codex and Kimi Review Each Other

I have three coding agents with access to this lab. Claude Code does most of the building. Codex reviews and runs the scans. Kimi audits. Until this week they had never exchanged a word — each got its own context, its own session, and its own chance to be confidently wrong with nobody checking. So I built a thing that makes them work one request together, and put a human approval gate in front of anything that changes the lab. ...

19 August 2026 · 11 min
Pipeline diagram: Codex scans 24 images and finds 2042 actionable findings, Claude Code fixes them one wave at a time behind a hard validation gate, then the same scanner measures again at 1497

A Vulnerability Scan From Codex, a Container Upgrade From Claude Code

I run two coding agents against this lab. Codex found the problem and Claude Code fixed it, and keeping those two jobs in different hands turned out to be the most useful part of the whole exercise. The short version: a full vulnerability scan reported 2042 actionable findings — 46 critical, 764 high — and 1751 of them were in container images. Ten waves of updates later, the same scanner reports 1497 actionable, 21 critical, 570 high. ...

18 August 2026 · 10 min
The agent auditor's local operator dashboard, showing observe-only mode and a list of recent Claude sessions with their recorded timelines

Auditing the AI Agent That Runs My Homelab

My homelab has picked up a lot of moving parts this year, and several of them are now LLMs. Claude Code runs natively on the box and does real work against real infrastructure — containers, reverse proxy config, monitoring, the lot. That’s genuinely useful. It also creates a trust problem I hadn’t had before. The problem is simple to state: the same agent that makes a change also writes the summary explaining why the change was safe. That’s convenient. It is not independent verification. If the agent quietly skips a validator and then reports “config validated”, I have no signal at all. The report is the evidence, and the thing that wrote the report is the thing being checked. ...

7 August 2026 · 9 min
The finished Release Watch workflow in n8n: schedule, state read, repo list, feed fetch, XML parse, decide, state write, and two ntfy branches

Patching a Homelab Has Two Halves — and Only One of Them Is apt

Two halves apt patches Debian. My homelab is not Debian — it’s about a dozen containers sitting on top of Debian. AdGuard, Authentik, Vaultwarden, Caddy, n8n, Greenbone, Homepage. apt will never once mention that Vaultwarden cut a release. So “keep the lab patched” is really two jobs: Debian packages — unattended-upgrades, already a solved problem, just needs scheduling and a report. Everything I actually run — nobody’s solved that for me. Containers only update when I decide to pull. This post is both halves. The first one taught me something uncomfortable about monitoring, so I’ll start there. ...

1 August 2026 · 13 min
Two rows: DNS resolution from host rig and phone through AdGuard to an upstream DoH resolver, and the admin UI reached only through Caddy and Authentik SSO

One DNS Filter, Three Clients That All Bypass It Differently

I wanted a DNS sinkhole in the lab — block ads, trackers, and adult content at the resolver instead of per-device. AdGuard Home is a single Go binary, so standing it up was maybe ten minutes. Then I spent the rest of the session learning that “point a device at the resolver” is a lie three times over. A Windows PC, an iPhone, and the lab host each route DNS somewhere I didn’t tell them to, for three completely different reasons. This is the write-up of finding all three. ...

1 August 2026 · 7 min
Langfuse's Tracing view showing a single claude_code.interaction trace with 2 observations and 3.40s latency

Implementing Langfuse to Monitor Claude Code

We all tend to focus on the output of whatever LLM we’re using — did it get the answer right, was it fast, was it useful. What I’d stopped paying attention to was the background: how many tokens a session was actually burning, where they went, and whether I’d have any way of knowing if something had gone quietly wrong. Claude Code runs natively on my homelab now, doing real work against real infrastructure, and I wanted more than “the output looked fine” as my only signal. ...

27 July 2026 · 4 min
Before/after diagram: Tailscale reaching one machine, versus a subnet router advertising 10.10.0.0/24 so the phone reaches the whole lab

Two VPNs, One Phone: Consolidating Remote Access

I ended up with two VPNs into my homelab. WireGuard, running on my firewall, which I set up first. And Tailscale on my main server, which I added later so I could SSH in from a laptop without opening ports. Then I tried to use both from my phone and hit a wall. Phones only run one VPN at a time This isn’t a bug or a conflict between the two apps. iOS and Android both allow exactly one active VPN tunnel, full stop. It’s an OS-level restriction. ...

24 July 2026 · 10 min
The finished four-node n8n workflow: Schedule Trigger, Execute Command, IF, and two ntfy alert nodes

Building a Backup Watchdog in n8n — and Finding a Five-Day Outage While I Did It

The problem I set out to solve My homelab takes a backup every night at 20:30. A cron job runs a script, the script dumps my Authentik database, snapshots the Vaultwarden vault, tars up the configs, encrypts a copy with age and drops it into OneDrive. It writes everything it does to /var/log/lab-backup.log. And nobody reads /var/log/lab-backup.log. That was the thing bothering me. If the backup silently stopped, I wouldn’t find out when it stopped — I’d find out the day I needed a restore, which is the worst possible day to learn anything. So the plan was simple: get n8n to check the backup actually happened, and buzz my phone if it didn’t. ...

23 July 2026 · 13 min
Homepage dashboard showing Infrastructure, Monitoring and Security service groups with live status dots

A Front Door for the Home Lab

At some point my lab crossed a line. I had a firewall, an identity provider, a password vault, dashboards, a log system, an alert router, and a vulnerability scanner — and I was typing subdomains from memory to reach any of them. Half the time I’d get one wrong. So this project is small: one page that links to everything. It took under an hour, and it’s the thing I now look at most. ...

23 July 2026 · 8 min
OpenVAS results page showing the first scan's findings by severity

Running OpenVAS in My Home Lab — Install, the Three Things That Broke, and the First Scan

I wanted a real vulnerability scanner in the lab — something that port-scans a host, throws a big pile of network vulnerability tests at it, and tells me what to fix by severity. OpenVAS (now Greenbone Community Edition) is the obvious choice, and it ships as a Docker stack. This is the honest write-up: the install, the three separate things that broke, one of which was my own fault, and what the scanner actually found when I pointed it at my own box. Nothing here is polished — I got a couple of things wrong along the way and I’m leaving those in, because that’s where the useful bits are. ...

22 July 2026 · 11 min
Grafana Explore showing pfSense firewall logs flowing through Loki, with a log-volume chart above

Building a Homelab SIEM with Loki — Reading My Logs Instead of Hoping

I had dashboards showing me numbers — CPU, memory, network throughput. What I didn’t have was any way to answer “what actually happened?” When did someone try to log in? What did the firewall block? Those answers live in logs, and my logs were scattered across machines, unread. This post is how I pulled them into one searchable place. That’s a SIEM — Security Information and Event Management — and you can build a simple one at home. ...

19 July 2026 · 7 min
RAINBOW MATRIX cover — the post title in rainbow monospace over falling matrix rain on black

Metrics You Have to Remember to Look At Aren't Monitoring

I’d had Grafana dashboards for months. What I didn’t have was anything that told me when something broke — I had to remember to look. This is the alerting layer that fixes that, built on top of the existing Prometheus stack, plus the three things that got in the way. Stack: Prometheus · Alertmanager · ntfy · Docker 1. The gap I’d been ignoring My lab had a healthy observability stack: Prometheus scraping metrics, node_exporter for the host, snmp_exporter pulling throughput off pfSense, all drawn in Grafana. It looked complete. ...

18 July 2026 · 12 min
RAINBOW MATRIX cover — the post title in rainbow monospace over falling matrix rain on black

A Backup You Haven't Restored Is a Hypothesis

The identity provider quietly became load-bearing and had no backup. Building one taught me more about database internals than building the identity provider did. Stack: Bash · Postgres · SQLite · age · cron · OneDrive 1. Purpose The identity provider started as a nice-to-have. Single sign-on for a dashboard — pleasant, not critical. Then it took over the firewall’s login. That’s the moment the risk profile changed, and it changed without any decision being made about it. Nobody sat down and said “let’s make the firewall depend on this container.” It happened one integration at a time, and the dependency graph grew quietly underneath. ...

16 July 2026 · 9 min
WireGuard handshake established over mobile data

Self-Hosted WireGuard Through a Nested Firewall — and the Four-Layer Debug to Make It Work

My lab is deliberately isolated — an automation VM (CLAUDDEB) sits behind a virtual pfSense firewall on a segment (10.10.0.0/24) that my home network can’t reach. That isolation is great until you’re out of the house and want to check your Grafana dashboards, which only listen inside that segment. I already use Tailscale for casual remote access, and I’ll be honest up front: for pure convenience, Tailscale wins — it punches through NAT automatically with zero firewall work. But this project wasn’t about convenience. It was about building the thing Tailscale is made of. Tailscale is WireGuard under the hood; hand-rolling raw WireGuard on pfSense teaches you how VPNs actually work — keys, peers, routing, firewall rules, NAT — at a level the managed tool deliberately hides. So I built it from scratch, kept Tailscale as my daily driver, and got a genuinely brutal debugging lesson in the process. ...

11 July 2026 · 7 min
A note pushed from the laptop appearing on the hub via get_recent

Syncing Claude Code Across Devices with a Custom MCP Hub over Tailscale

I run Claude Code on two machines: the Debian VM in my home lab (always on) and a Debian laptop (sleeps, roams, follows me to campus). I wanted the laptop to push notes, facts, and findings into a central store on the VM — from any network — so the home-lab agent could pick them up later. Claude Code’s built-in Remote Control turns a second device into a remote window onto one session. That’s not what I wanted. I wanted both machines to stay fully independent agents, linked through a shared tool. So I built a small MCP server on the VM and pointed the laptop’s Claude Code at it: the hub becomes just another tool the laptop can call. ...

7 July 2026 · 6 min
Grafana Node Exporter dashboard for the Debian VM

Building a Prometheus and Grafana Observability Stack for My Home Lab

My LaMetric display gives an at-a-glance read on the lab, but it’s a spot reading with no history — good for “is something on fire right now,” useless for “what happened overnight.” This project adds the layer underneath: a Prometheus + Grafana stack that scrapes my hosts continuously, stores the history, and draws real dashboards. Two targets: CLAUDDEB (my Debian automation VM) and my pfSense firewall, reusing the exact SNMP setup from the pfSense post — just pointed at something far more capable than a 37-pixel display. ...

6 July 2026 · 6 min
pfSense WAN byte counter climbing under SNMP polling

Implementing LaMetric TIME to Network Part 2

In part 1 I got a LaMetric Time showing live health from my home lab over MQTT, so it worked across my network isolation — CPU, memory, disk, uptime, and the automation VM’s own traffic, all from a single Debian box. Useful, but those were really that box’s stats. The frame the display was named for is my network’s throughput — the traffic crossing my firewall — and that data lives on pfSense, not the Debian box. This is the follow-up: pulling real WAN in/out rates off pfSense over SNMP and putting them on the display. It’s shorter than the MQTT build, because the pipeline already exists; all I’m adding is a new data source. Getting numbers out of pfSense is the part worth writing down. ...

6 July 2026 · 8 min
A LaMetric Time smart display

Implementing LaMetric TIME to Network

I picked up a LaMetric Time — an 8x37 pixel smart display — and after locking it down on an isolated guest network, the next move was to make it useful: live health from my home lab. CPU, memory, network throughput — the numbers worth a glance. The interesting part is that a constraint I’d deliberately built into my network dictated the whole architecture. This is the write-up: the design decision, the pipeline, and the gotchas — because the gotchas are the useful part. ...

5 July 2026 · 7 min
pfSense dashboard after the rebuild

Debugging a Dead VMware NAT and Hardening My pfSense Containment Lab

I run my Claude Code work inside a Debian 13 VM (CLAUDDEB) on VMware Workstation Pro 17.6.4, with a pfSense 2.8.1 VM in front of it as a virtual router and firewall. pfSense exists in this setup for containment: if something on the Debian VM misbehaves — a prompt injection, a compromised dependency — it must not be able to reach my PC, my router’s admin page, or anything else on the home network. ...

2 July 2026 · 7 min