Skip to content

docs(adr): buy ifrit for IOPS and keep the range disposable (#96) - #258

Merged
Gerrrt merged 2 commits into
mainfrom
gerrrt/procure-ifrit-build-playground-fb98b2
Sep 4, 2026
Merged

docs(adr): buy ifrit for IOPS and keep the range disposable (#96)#258
Gerrrt merged 2 commits into
mainfrom
gerrrt/procure-ifrit-build-playground-fb98b2

Conversation

@Gerrrt

@Gerrrt Gerrrt commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Closes #96 — as far as documents can. The purchase and the build are the two things left, and both need hardware that does not exist yet.

What this issue actually still contained

The issue calls ifrit's deferred isolation mechanism "the real content", and it was — but ADR-0014 already answered it, jointly with #86. roadmap.md agrees: "What is left is the purchase and a build runbook that checks each of those."

What ADR-0014 did leave were three adjectives:

  • "sized for on-demand use" (ADR-0007) — no purchase spec.
  • "a subnet deliberately outside 10.0.0.0/16" — a runbook cannot be written against an adjective.
  • Nothing at all about whether the range's guests are backed up, monitored or patched — and the estate's answer to each is already yes, which is the wrong answer here.

ADR-0017 pins those. build-the-playground.md is the runbook ADR-0014 asked for when it said its constraints are "checked by the build runbook rather than assumed".

The purchase

Following ADR-0016's discipline — decide the half that cannot be changed later, choose the rest at the till:

Decided Why it cannot wait
NVMe, no mirror The range's core operation is snapshot revert. ADR-0007 already records the fleet's complaint as spindles, not RAM — buying a second box with Saruman's shape buys the same complaint twice
Socketed RAM, two slots, 32 GB fitted prometheus's is soldered at 8 GB. That ceiling was bought by accident
Quiet SFF, not rack-mount ADR-0007 paid the DL360's acoustic cost once, in an occupied office, and disliked it
One NIC ADR-0014 lists "a second physical NIC" as a trigger to reopen it

No redundancy, deliberately: ADR-0016 gave the NAS a mirror because the requirement was availability. Here the recovery model is rebuild, and two disks protecting contents that are deliberately worthless is the kind of consistency that isn't one.

The addresses

172.30.30.0/24 on the isolated bridge, with no default route anywhere on it and no address on the host.

Rejected: 192.168.0.0/16 (the default of nearly every vulnerable image, and a 192.168 source is the least remarkable line in a log), 100.64.0.0/10 (Tailscale's), and any further 10.0.0.0/16 — ADR-0014 forbids it, because a leak has to miss the ImaginationLAN pass rule to be caught by default deny. The /24 sits high in 172.16.0.0/12 because Docker's pool walks that block upward from 172.17.

No DHCP on the bridge: the obvious place to run it is the dual-homed VM, and a DHCP server that binds the wrong interface there is rogue DHCP on the segment holding the estate's hypervisor and its BMC.

ifrit takes 10.0.30.30, leaving .20 clear for Saruman — whose move out of the Kea pool ADR-0014 requires "at the same time", so it is a step in the runbook rather than a detail of it.

The upkeep: none, and that is the decision rather than the omission

  • No backups. A deliberately-vulnerable image in the estate's backup store is a supported path for it to arrive somewhere it should not be.
  • No monitoring. ifrit is off by design, so every rule watching it is permanently firing or permanently silenced — and it would need a pass into Winterfell that ADR-0014's "one log-only tripwire, zero passes, zero blocks" accounting does not have.
  • No patching of the guests. The host is patched, because the host is the isolation mechanism.

"After the main network is finished" now names issues

Not gates, said explicitly so it isn't assumed: #228 waits on this build's list of what a Hicks workstation reaches, and #229's exposure runs in the direction the range does not travel.

The runbook

Each of ADR-0014's four properties gets a command, and §9 proves the "a leak reports itself" claim by deliberately causing one and finding the block in Loki with a 172.30.30.x source.

Two traps it names:

  • Enabling the Proxmox datacenter firewall brings the per-NIC guest flag to life, and that flag is set by default on any NIC added through the GUI. A range whose hypervisor quietly filters its own guests lies to you about what your tooling did — clearing it is what makes ADR-0014's "guests are unaffected" true rather than assumed.
  • Installing Docker on the attack VM sets ip_forward=1 at daemon start, whatever the sysctl file says, and does it again every boot.

Also in here

ADR-0014 gets a forward-pointer note; network.md, security.md and roadmap.md carry the subnet and the addresses. ADR-0017's Consequences record two things it found and did not decide: 8007 on ifrit will admit nothing (ADR-0014 wrote one management rule for two hosts, and this one gives ifrit no PBS), and nothing in the estate knows whether the range is powered — there is no cheap alert shape for "this host is on when it should be off".

make validate passes.

🤖 Generated with Claude Code

ADR-0014 settled where `ifrit` goes and left three things as adjectives.
ADR-0017 pins them, and `build-the-playground.md` is the runbook ADR-0014
asked for when it said its constraints are "checked by the build runbook
rather than assumed".

The purchase: NVMe not a spindle, because the range's whole operation is
snapshot-and-revert and ADR-0007 already records that the fleet's complaint
is spindles rather than RAM; socketed RAM in two slots, because
`prometheus`'s is soldered and that ceiling was bought by accident; quiet
and not rack-mount, because ADR-0007 paid the DL360's acoustic cost once in
an occupied office. Capacity, CPU and the memory kit are chosen at the till
and recorded in `hardware.md`, the same split ADR-0016 used for the NAS.
No redundancy: the recovery model is rebuild.

The addresses: `172.30.30.0/24` on the isolated bridge, and nothing on it
has a default route — `192.168.0.0/16` is the default of every vulnerable
image, `100.64.0.0/10` is Tailscale's, and any further `10.0.0.0/16` is
forbidden by ADR-0014 because a leak has to miss the ImaginationLAN pass to
be caught by default deny. `ifrit` takes `10.0.30.30`, leaving `.20` clear
for `Saruman`'s move out of the Kea pool, which ADR-0014 requires at the
same time and which is a step in the runbook.

The upkeep: none. No backups, because a deliberately-vulnerable image in
the estate's backup store is a supported path for it to arrive somewhere it
should not be. No monitoring, because a host that is off by design makes
every rule watching it permanently firing or permanently silenced, and it
would need a pass into Winterfell that ADR-0014's rule accounting does not
have. No patching of the guests; the host is patched, because the host is
the isolation mechanism.

"After the main network is finished" now names issues: #101 first, because
an attack VM pointed at an uninstrumented estate teaches nothing; #234
before the segment holds attackers; #235 decided before this build makes it
true. #228 and #229 are explicitly not gates, and the ADR says why.

The runbook checks each of ADR-0014's four properties with a command, and
§9 proves the "a leak reports itself" claim by deliberately causing one and
finding the block in Loki. Two traps found on the way: enabling the Proxmox
datacenter firewall brings the per-NIC guest flag to life, and a range
whose hypervisor quietly filters its own guests lies to you about what your
tooling did; and installing Docker on the attack VM sets `ip_forward=1` at
daemon start whatever the sysctl file says.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 4, 2026 03:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few concrete documentation/runbook correctness issues (a truncated sentence and non-portable grep patterns) that should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR closes out the remaining documentation work for the ifrit playground decision by adding ADR-0017 and a concrete build runbook, and then propagating the chosen address plan and “disposable range” stance into the network/security/roadmap docs.

Changes:

  • Add ADR-0017 defining purchase constraints, 172.30.30.0/24 for the isolated bridge, and the explicit “no backups/monitoring/guest patching” policy for the range.
  • Add docs/runbooks/build-the-playground.md to operationalize ADR-0014’s constraints with explicit verification commands and a leak-proof test.
  • Update security/network/roadmap/ADR-0014 to reference ADR-0017 and the runbook, and to pin the chosen subnet/address details.
File summaries
File Description
docs/security.md Updates threat-model row with the finalized unrouted target subnet and ADR references.
docs/runbooks/build-the-playground.md New end-to-end runbook for building and validating the isolated playground on ifrit.
docs/roadmap.md Expands the #96 roadmap entry with ADR-0017’s purchase/address/upkeep decisions and links to the runbook.
docs/network.md Pins ifrit/range addressing and documents the unrouted 172.30.30.0/24 bridge behavior.
docs/adr/0017-buy-ifrit-for-iops-and-keep-the-range-disposable.md New ADR capturing purchase constraints, addressing, and “disposable range” maintenance policy.
docs/adr/0014-put-ifrit-on-imaginationlan-and-give-the-targets-no-route.md Adds a forward-pointer note to ADR-0017 + runbook without amending ADR-0014’s core constraints.
Review details

Suppressed comments (1)

docs/runbooks/build-the-playground.md:302

  • Same portability issue here: the grep alternation uses | in basic regex mode. Use -E and a plain | so the command behaves consistently across grep implementations.
nft list ruleset 2>/dev/null | grep -i 'masquerade\|snat' || echo "no NAT"
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/runbooks/build-the-playground.md Outdated
Comment thread docs/security.md Outdated
Review feedback on #258. Two greps used GNU basic-regex alternation in
commands meant to be copied and pasted; both are now `-E` with a plain `|`.

The VLAN-aware check changes what it matches while it is there: the old
pattern's two alternatives were the same test, since `vlan-aware` already
matches `bridge-vlan-aware`. Proxmox writes `bridge-vids` alongside it on a
VLAN-aware bridge, so that is the second marker worth looking for.

And the threat-table row in `security.md` ended on "a default route to" with
no object.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Gerrrt
Gerrrt merged commit e377891 into main Sep 4, 2026
3 checks passed
@Gerrrt
Gerrrt deleted the gerrrt/procure-ifrit-build-playground-fb98b2 branch September 4, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Procure ifrit and build the playground — after the main network is finished

2 participants