Repository navigation
Conversation
eden (141, BloodHound) was a hand `qm clone 901 141`, so tofu could not rebuild it (#1443, audit finding 18). It is now in guests.tf, in a `bloodhound` pool, with ADR-0081's shape: the OS disk on local-lvm without the SSD flag, a 32 GiB data disk on large_data, a static 10.0.30.41 with its gateway and nameserver, and garnet's key from alexander beside phoenix's. The module gains os_disk_ssd, data_disks, ipv4 and dns_servers. Each defaults to what every other guest has, so their plans do not change. The hand-built eden is imported once. As with the domain's six, the plan then replaces it, because a hand-built guest has no clone to read back. ADR-0081 allows that: the graph is derived data and eden is not backed up. The runbook says so, then destroys and applies, then continues from section 2, with section 11 for the new key. Refs #1443 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2EweeKAdMf5A1aeFy1anN
There was a problem hiding this comment.
🟡 Changes recommended
The domain rebuild would destroy BloodHound’s disks, graph, and unbacked-up age key, while the migration instructions attempt an apply before importing the existing VM.
2 open issues
What changed in this PR
This PR brings eden, the BloodHound CE guest, into the OpenTofu provisioning pipeline. It implements the eden portion of #1443; ragnarok remains separate.
Changes:
- Declares eden’s storage, networking, resources, operator key and pool.
- Extends the guest module with optional disk and network settings while preserving existing defaults.
- Documents pipeline creation, destructive migration of the hand-built guest, and teardown.
| File | Description |
|---|---|
tofu/variables.tf |
Adds eden’s operator public-key file input. |
tofu/README.md |
Lists eden among pipeline-managed guests. |
tofu/modules/guest/variables.tf |
Defines optional disk and network inputs. |
tofu/modules/guest/main.tf |
Implements additional disks and configurable network settings. |
tofu/identities.auto.tfvars.example |
Adds an eden MAC placeholder. |
tofu/guests.tf |
Declares eden and passes its settings into the guest module. |
docs/runbooks/provision-lab-guests.md |
Documents the BloodHound pool permission grant. |
docs/runbooks/build-the-bloodhound-guest.md |
Replaces manual provisioning with pipeline and migration procedures. |
Review effort: Balanced
|
Validate configs failed for a reason this PR didn't cause. Lint passed on this head, which means Generated by Claude Code |
…sends a migration to the import first build-the-lab-domain.md step 5 destroyed with -target=module.guest, which is every Saruman guest in the tree: garuda, the dotfiles VMs and, with this PR, eden. That would take garuda's case notes and eden's graph with the domain, against ADR-0081's reason for putting BloodHound off it. Steps 5 and 7 now target the six by name, and tofu/README.md and provision-lab-guests.md §2 say so. build-the-bloodhound-guest.md §1 put the first-build plan and apply before the import subsection. Followed in order against the existing eden, the apply fails on the clone into 141 after making the pool. A migration is now sent to the import before any apply. Refs #1443 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2EweeKAdMf5A1aeFy1anN


What changed
eden(141, BloodHound CE) is declared intofu/, so the pipeline can rebuild it. This is the first half of #1443;ragnarokfollows in its own PR.tofu/guests.tf: abloodhoundlocal witheden, in a newbloodhoundpool, with ADR-0081's shape asbuild-the-bloodhound-guest.md§0 tabulates it:local-lvm, without the template'sssdflag;large_dataasscsi1;10.0.30.41/24with the gateway and nameserver10.0.30.1;bloodhoundandon-demand, andonbootoff;garnet, withalexander's key besidephoenix's.tofu/modules/guest: four new inputs, each defaulting to what every other guest has, so the other 20 guests' plans don't change:os_disk_ssd,data_disks,ipv4anddns_servers.tofu/variables.tf:eden_operator_key_file, with default~/.config/proxmox/eden-garnet.pubonphoenix.identities.auto.tfvars.example: anedenplaceholder MAC.build-the-bloodhound-guest.md§1 now builds fromphoenix. It gains a once-only "bring the hand-builtedeninto the pipeline" step, and §10's teardown is a tofu destroy.provision-lab-guests.md§2 gets the/pool/bloodhoundgrant and its row.tofu/README.mdlists the guest.Why
Item 18 of the 2026-11-11 audit:
edenwas a handqm clone 901 141, outside ADR-0076's pipeline. The owner chose to declare it, and to do it beforeragnarok, which waits on the gandalf provider.One change from #1443's plan. #1443 asked for an import that plans No changes. The repo's own record (
build-the-lab-domain.md, step 4 of the rebuild) shows that importing a hand-built guest always plans a replace, because a running guest'sclonecan't be read back. ADR-0081 makes that acceptable foreden: its graph is derived data, it has no backup, and it is "rebuilt from this repository". So the runbook goes import → plan (expect exactly one replace, plus the pool) → destroy → apply. It then continues from §2, with §11 for the new age key.Refs #1443
Blast radius
edenitself. When the runbook's once-only step is run, it is destroyed and rebuilt. Its graph, its Postgres data and its age key go with it, as ADR-0081 accepts. Nothing else onSarumanchanges.The other guests: their module inputs default to their current values. If
tofu fmt/validate, or the first plan onphoenix, shows a change to any other guest, that is a bug in this PR and a stop.Nothing happens until someone runs it on
phoenix. Merging changes no host.No change to network segmentation or firewall rules
No new port published to a VLAN that could not already reach the service
No credential added outside
secrets/*.sops.yaml. The new file onphoenixholds a public key.Verification
All four changed
.tffiles parse with python-hcl2.tofu fmt -checkandtofu validatewere not run here: this session has no tofu and no Docker to run it in. CI's Lint job runs both../scripts/lint.sh: passed, 7 skipped (packer, tofu ×3, ansible-lint and the editorconfig-checker container).ecwas run directly on the changed files and passed.python3 scripts/check_docs.py: OK.check-tracked-artefacts.sh: OK.The real proof is on
phoenix:plan -target='module.guest["eden"]'after the import must show exactly one replace plus thebloodhoundpool. A plainplanmust show no change to any other guest.make validatewas not run in full: no Docker here. lint,check_docsand the artefact check above were.Deployed to the lab and confirmed working: not yet. The runbook's once-only step on
phoenixis the deploy.Docs updated (
docs/, service README, ordocs/roadmap.md)Generated by Claude Code