Operator ruling ("I'll defer to your lean"): the OPNsense config.xml template is deleted, not reduced.
The (a2) plan was to shrink the template to a minimal bootstrap (sshd + root key + console + a seeded API key). That turned out to be unnecessary -- every one of those is covered without a config.xml at all:
| bootstrap need | how it is met now |
|---|---|
| sshd + root key | the D-112(c) console bootstrap (proven on Office1) |
| an API key | opnsense-bootstrap-apikey.sh -- calls OPNsense's OWN model over SSH; no GUI click, no re-implemented crypto |
| DHCP / firewall / interfaces | the REST API (opnsense-api.sh), proven read AND write |
So the provisioning chain contains no config.xml anywhere:
boot factory nano -> console bootstrap -> mint API key -> configure over REST
A config.xml renderer that nobody should ever run is not a safety net -- it is a loaded gun pointed at a live router. The 2026-07-13 safety sweep is the evidence: the repo still contained runbook steps telling an operator to render a config and push it to the edge, which by then would have clobbered live API-managed DHCP.
opentofu/templates/opnsense-config.xml.tmplscripts/opnsense-render-config.sh + tests/opnsense-render-config/scripts/opnsense-build-config-iso.sh + tests/opnsense-build-config-iso/opnsense-edge module's config_seed volume + cdrom disk, and its config_iso_path varxorriso/genisoimage prereq (it existed ONLY for the ISO builder)All remain in git history. opentofu/templates/README.md is now a tombstone explaining what happened and what to use instead -- people will go looking for that template.
Removing the module's ISO wiring touches an INSTANTIATED resource (libvirt_volume.config_seed is in tfstate). Measured with tofu plan BEFORE applying:
module.office1_opnsense.libvirt_domain.vm will be updated IN-PLACE module.office1_opnsense.libvirt_volume.config_seed will be destroyed Plan: 0 to add, 1 to change, 1 to destroy.
No replacement of the running domain -- confirmed explicitly (a replacement would have destroyed the live edge). Only the cdrom entry is removed from the disk list and the inert ISO volume is dropped.
The apply RESTARTED the guest. This was predicted NOT to happen, and that prediction was WRONG. Measured: uptime went from 8:36 to 6 secs across the apply. The dmacvicar/libvirt provider redefines the domain to apply a disk-list change and bounces it -- there was a brief outage (~30s) during which the edge was not routing and not serving DHCP.
libvirt_domain ... will be updated in-place means the RESOURCE is not replaced. It says NOTHING about whether the GUEST keeps running. Do not read it as "no interruption".
This matters for Stage 3. Any future tofu apply that touches a libvirt_domain's devices -- on a DC edge, or on a node VM -- should be assumed to BOUNCE THE GUEST, and must be scheduled and gated as an outage, not as a no-op config tidy-up.
Recovery was clean and needed no intervention: post-boot, kea-dhcp4 is running and bound to 10.10.0.1:67 with the subnet/pool intact, WAN/LAN/default-route up, egress 0.0% loss, 8 LAN pass rules in pf, serial console + getty alive. tofu plan reports "No changes" -- repo and state are back in sync.
Applying it now was the SAFE choice, not the risky one. Leaving the repo/state divergence in place would mean the next tofu apply -- e.g. while building DC1's substrate in Stage 3 -- sweeps up this pending change as a surprise side effect on the running Office1 edge, mid-stage. Deliberate and gated beats incidental and unnoticed.
repo-lint's L3 rule (runbooks must not reference missing scripts) went RED on the tombstone notes, because they named the deleted paths. The rule was RIGHT, and it has no opt-out (only L4 does). Rather than weaken a guard that exists to stop runbooks pointing at dead scripts, the tombstones were reworded to name the bare filename instead of the scripts/ path. The guard stays fully intact; the information is preserved.
repo-lint 0 fail. opentofu-validate PASS -- root + 10/10 modules standalone. Gauntlet green.
git revert <this commit> # restores the template, renderer, ISO builder, harnesses cd opentofu && tofu apply # re-creates the (inert) config_seed volume + cdrom
Nothing depends on the ISO: it was never read by anything (D-112).