This is the whole thing in one place: a segmented VMware lab behind a pfSense firewall, one identity provider enforcing MFA everywhere, a full metrics-and-logs monitoring stack, and encrypted off-site backups that have actually been restored. It runs on a single gaming PC and it’s built to be operated, not just stood up — so the point of this page isn’t the parts list, it’s how they fit and what happens when one breaks.
The Lab
Topology at a glance
Want the design underneath it — addressing, trust zones, the firewall policy matrix? See the network design →
How it's actually run
No pretending this is a datacentre. It's a virtual lab on one machine — so here's the real operating model, including what it doesn't do yet.
The machine it all runs on
No rack, no datacentre — every VM in the diagrams above lives on one desktop PC. Here's the hardware underneath, and how much of it the lab is actually given.
What the lab actually gets
Everything on the topology diagram sits inside that one slice. The rest of the box carries Windows and the pfSense VM — which is exactly why the lab is a nightly-shutdown environment and not an always-on one.
The AI plane
Three coding agents have real access to this lab, so the interesting question is not which models run here — it is what sits between them and anything that matters. Read it top down: every tier constrains the one beneath it.
Controls
What actually stops a bad change. Deterministic, not prompt instructions.
- Human approval bound to a SHA-256 of the exact plan — edit the plan, the approval is void
- Exclusive scope claims, so two agents cannot work the same service
- Intent recorded before a change; an unsettled one blocks any automatic retry
- Fail-closed redaction on every message stored, shown, or passed between agents
Orchestration
One request, three agents, a structured review rather than three opinions.
- Round 1 answered blind and committed before anyone sees anyone else
- Round 2 each reviewer sees the others' findings as labelled data
- Further rounds only when an agent asks for one
- A fourth model merges the panel and lists unsupported claims separately
Agents
Different powers on purpose — the one that builds cannot be the one that signs off.
- Claude Code — plans, and is the only agent permitted to change anything
- Codex — implementation and test plans, review; prepares but never deploys
- Kimi — independent read-only audit, behind an integrity-checked launcher
Gateway
One endpoint for every model, with the spend limit enforced outside the caller.
- LiteLLM routes, authenticates and caps spend per virtual key
- Open WebUI for humans, behind single sign-on; the API takes keys, not logins
- Per-project keys scoped to specific models with their own budget
Observability
Every call recorded, so a claim about what an agent did can be checked.
- Langfuse traces every gateway call and every Claude Code session
- A hash-chained evidence ledger for agent tool calls, projected into the SIEM
- Tamper-evident, not tamper-proof — and the docs say so
How the three agents actually review one request: Three agents, one approval gate →
Every layer, every component
The lab as defence in depth — and every box below links to the post where I built it.
Boundary & network
A firewall VM is the only thing the rest of the lab talks to the world through — default-deny, private ranges blocked outbound, segmented into isolated zones.
Identity & access
One identity provider with MFA is the single login authority — for web dashboards and for the firewall's own admin login. Who you are and what you may do are decided in one place.
Compute & automation
One hardened Debian VM hosts the containers and the agent workflow. It runs the services above and the monitoring below, and it's locked down as its own audited surface.
Observability & detection
Metrics answer 'what's the number', logs answer 'what happened', and alerts reach out so nothing waits to be noticed. Dashboards, alerting, and a log SIEM on one stack.
Resilience & edge
The parts that decide whether the lab survives a bad day: encrypted off-site backups that have actually been restored, and a physical glance display that never crosses the isolation boundary.
From signal to phone
Both halves of monitoring feed one alert path: a number crossing a threshold, or a log line matching a pattern, ends up as the same buzz in my pocket — with an all-clear when it resolves.
Runs while the lab is up. The nightly shutdown is exactly why alert rules wait 10m before firing — so a morning boot isn't mistaken for an outage.
Every rule on that path — the live LogQL/PromQL and its ATT&CK mapping — is catalogued: See the detections →