Executed the live apply of the Kea DHCP config built (but deliberately NOT applied) under DOCFIX-193. The Office1 OPNsense edge is now a router and a DHCP server for office1-local.
Target: root@10.10.0.1 (office1-opnsense), the live, routing Office1 edge. Path: the D-112(c) steady-state path -- render -> scp over SSH -> SHA-256 verify on the guest -> install to /conf/config.xml -> reboot.
set -a; . ~/vr1-office1.env; set +a bash scripts/opnsense-render-config.sh "$OPNSENSE_CONFIG_OUT" scp -i "$OPNSENSE_SSH_KEY" "$OPNSENSE_CONFIG_OUT" root@10.10.0.1:/tmp/config.new # guest: sha256 -q /tmp/config.new == local sha256, else abort # guest: cp /tmp/config.new /conf/config.xml ; reboot
Rendered config sha256 bc100bd49c9d2bfec7dfd799e03da7cc5fa48a2608a6521ed2dfea645366a9be; guest hash matched before install. Edge returned in ~30s.
kea-dhcp4 running (pid 15090), bound udp4 10.10.0.1:67 -- the deliverable.enabled=1, interfaces=lan, subnet 10.10.0.0/24, pool 10.10.0.100-10.10.0.199, routers/DNS 10.10.0.1.172.30.1.2, LAN 10.10.0.1, default route 172.30.1.1, NAT automatic, egress to 1.1.1.1 0.0% packet loss.kern.console=ttyu0, getty running (DOCFIX-192 holds).NOT yet verified end-to-end: an actual client DHCPDISCOVER->lease. No client exists on office1-local yet. The udp/67 binding + loaded subnet is the strongest available evidence until Stage 2 puts a host on that LAN.
A full-config push REPLACES /conf/config.xml wholesale. The rendered template is 128 elements; the live config was 796. The overwrite therefore drops 667 elements that OPNsense's own migrations had populated -- including, critically:
/OPNsense/Firewall/Filter/rules/rule x2 "Default allow LAN to any" (+ IPv6)
Those two MVC rules are the ONLY pass rules on the box (/filter/rule count is 0 -- the legacy rules were migrated away in 26.1), and pf's base policy is block drop in log inet all. Dropping them with no replacement = an edge that boots but does not route.
This was NOT resolved by inference. It was settled from the box's own /conf/backup/ trail, which shows the overwrite is self-healing and had already been exercised three times on this exact host:
| time (07-12) | elements | MVC rules | legacy /filter | revision |
|---|---|---|---|---|
| 07:50 | 713-733 | 0 | 2 | factory nano; rules live in legacy /filter |
| 20:25 | 774 | 2 | 0 | after a template push (0 rules) + boot -> run_migrations |
| 23:28 | 776 | 2 | 0 | after a template push (0 rules) + boot -> run_migrations |
| 23:30 | 796 | 2 | 0 | after a template push (0 rules) + boot -> run_migrations |
Every push of a rule-less config came back with exactly 2 regenerated default-allow-LAN rules and working routing. The same trail shows Created web GUI TLS certificate after each boot, so /ca, /cert and /system/webgui/ssl-certref regenerate too.
Today's apply was cycle #4 of that proven mechanism plus one additive block, and the post-reboot measurement confirms it: 791 elements, both LAN rules back, TLS cert back, and our subnet4 survived the migration pass.
Step 1 of the apply -- the pre-install snapshot -- silently failed:
ssh root@10.10.0.1 'cp /conf/config.xml /conf/config.xml.pre-dhcp && echo "... $(sha256 -q ...)"' -> Illegal variable name.
root's shell on OPNsense is tcsh, not sh. The $(...) inside the quoted remote command is parsed by tcsh, which rejects it -- and because the failure was non-fatal, the install proceeded without the named rollback point. The config was recoverable anyway (OPNsense keeps /conf/config.xml.prev + /conf/backup/), so no harm resulted, but the guard did not exist when it was relied upon.
Lesson for the apply path: every remote command to this box must be fed to sh -s (as the install and verify steps correctly were), never passed as a quoted string to root's tcsh.
The apply path is still ad-hoc shell, not a repo script with a harness -- which is why the tcsh defect above could ship at all. It should become scripts/opnsense-apply-config.sh (snapshot -> scp -> verify -> install -> reboot -> assert), with the assertions from this session (kea on udp/67, 2 LAN rules, egress, console) as its post-conditions. LOGGED, not executed -- it is out of scope for this step.
ssh -i "$OPNSENSE_SSH_KEY" root@10.10.0.1 'sh -s' <<'SH' cp /conf/config.xml.prev /conf/config.xml && reboot SH
Restores the pre-DHCP routing config (the edge routes; nothing serves DHCP). Repo-side, DOCFIX-193 (7a2b396) is the commit that introduced the Kea template block.