Context. Standing up the Office1 OPNsense edge so office1-local has a router + DHCP (operator: bring the edge online before the Office1 NetBox VM). First-ever OPNsense boot in this repo -- reviewed-but-unexercised module + image chain. This records the repo changes and the two real infrastructure findings hit on the first apply.
opentofu/main.tf: module "office1_opnsense" instantiated (was a commented skeleton): modules/opnsense-edge, 2 vCPU / 2 GiB / 16 GiB, pool_name = module.office1_storage.pool_name, base_volume_path = the prepped nano qcow2, config_iso_path = the staged config ISO, lan_network_name = module.office1_network.network_name, wan_network_name = "office1-wan". Validated + planned clean (first real validation of modules/opnsense-edge): 3 to add.office1-wan NAT network (172.30.1.0/24 -> enp1s0), created via virsh -- Office1's per-site simulated-ISP uplink (operator's per-site-uplink ruling). Logged as D-103 debt to formalize into an OpenTofu module later (same class as the retained wan).~/vr1-office1-creds/ (jumphost-only, NEVER committed): SSH keypair + root password + its bcrypt hash (for config.xml).config_iso_path must live OUTSIDE the pool dir. libvirt_volume.config_seed uses create.content.url to COPY the ISO into the pool as a volume named office1-opnsense-config.iso; if the source ISO sits at that exact pool path, libvirt errors "volume target path ... already exists". Fixed by staging the ISO at /var/lib/libvirt/vr1/staging/ and pointing config_iso_path there. (The disk uses backing_store -- a reference, not a copy -- so the in-pool nano image is fine.) CORRECTION 2026-07-12 (DOCFIX-189): that parenthetical is now STALE -- DOCFIX-187 changed the disk to a direct copy (create.content.url), so it no longer uses backing_store. The in-pool nano image is still fine, but for a DIFFERENT reason: the copy's target volume name (<vm>-disk.qcow2) differs from the source (opnsense-26.1-nano.qcow2), so there is no target-path collision. Same conclusion, different mechanism -- do not rely on the original reasoning./var/lib/libvirt/vr1/. The domain was defined but failed to start: qemu (libvirt-qemu) got "Permission denied" on the backing image despite correct POSIX perms. libvirt's apparmor abstraction only whitelists /var/lib/libvirt/images/** + .../qemu/**, not our operator-owned vr1/ pool tree. This is foundational -- every VR1 VM lives under /var/lib/libvirt/vr1/. Fix (operator, one-time sudo), via the abstraction's include if exists <local/abstractions/libvirt-qemu>:
echo '/var/lib/libvirt/vr1/** rwk,' | sudo tee /etc/apparmor.d/local/abstractions/libvirt-qemu sudo systemctl reload apparmor && sudo systemctl restart libvirtdPREREQ: this belongs in the workstation/host prep (a candidate
scripts/prereqs/ addition + a phase-0/phase-1 runbook note) since it gates every VR1 VM boot, not just this edge. Not yet actioned as a prereq installer (needs sudo).office1-wan, creds, config, ISO, module instantiation, disk + config_seed volumes all done. Domain boot is blocked ONLY on the apparmor fix above (operator sudo). After it: re-apply to boot, then verify WAN (172.30.1.2)
office1-local.git checkout opentofu/main.tf (re-comment the module); virsh net-destroy/undefine office1-wan; git rm this changelog. (Live volumes: tofu destroy the office1_opnsense module resources.)