| .. | |||
| README.md | 10 hours ago | ||
| opnsense-config.xml.tmpl | 10 hours ago | ||
opnsense-config.xml.tmpl is the {{TOKEN}}-parameterized OPNsense config.xml for a DC-DC edge (Office1, DC1, or DC2 -- one instantiation per site). Built directly from OPNsense's own real, currently-shipped config.xml.sample (opnsense/core, fetched 2026-07-09 -- see .claude/skills/openstack-cloud-ops/references/opentofu-provider-docs.md for the fetch method) plus the confirmed staticroutes schema (opnsense/core's Route.xml model). This is real design work, not a placeholder -- but several tokens genuinely cannot be filled with a real value yet because the decisions they depend on (D-100/D-101/D-107) are still PROPOSED, or because the value can only be measured on a real boot. Never invent a value for those; leave the token required and unfilled until the real one exists.
opnsense-config.xml.tmpl --(scripts/opnsense-render-config.sh, env-var tokens)--> real config.xml --(scripts/opnsense-build-config-iso.sh)--> config.iso (plain ISO9660, /conf/config.xml) --(opentofu/modules/opnsense-edge, config_iso_path variable)--> attached as a secondary cdrom disk to the domain
| Token | Status | Notes | |
|---|---|---|---|
{{OPNSENSE_HOSTNAME}} |
Design choice, not yet made | e.g. opnsense. NOT named HOSTNAME -- that collides with bash's own built-in $HOSTNAME variable (caught by this delivery's own test harness: unset HOSTNAME doesn't actually clear it, since bash repopulates it). |
|
{{DOMAIN}} |
Real, applies D-106's naming convention | e.g. omega.dc1.vr1.cloud.neumatrix.local, following the (still-PROPOSED, but already-settled-as-design-intent) <service>.omega.<dc>.vr1.cloud.neumatrix.local pattern -- same status as DC1's plane CIDRs elsewhere in this repo: carried-forward design intent, not invented. |
|
{{ROOT_PASSWORD_HASH}} |
MUST be freshly generated, never reused | The real config.xml.sample ships a bcrypt hash ($2y$10$...) for a well-known default OPNsense password -- reusing it verbatim would mean every edge shares a public default root password, a real exposure. Generate a fresh one per deployment, e.g. `htpasswd -bnBC 10 "" '' \ |
tr -d ':\n'(produces a$2y$10$...`-compatible bcrypt hash) -- NOT independently verified against a real OPNsense login this session; confirm login works before relying on it operationally. |
{{NTP_UPSTREAM_SERVERS}} / {{NTP_PREFER_SERVER}} |
Real default supplied (optional to override) | Defaults to the exact same public pool OPNsense's own sample ships (N.opnsense.pool.ntp.org) -- a real, confirmed default, not invented. D-107 says the edge "syncs upstream to internet NTP pools," consistent with keeping this default. Override only if a different upstream is decided. |
|
{{WAN_IF}} / {{LAN_IF}} |
MUST be measured on a real boot | The <if> value is the actual vtnetN (or similar) device name FreeBRSD assigns -- confirmed from the real sample that this, not interface declaration order, is what assigns the LAN/WAN role (see opentofu/README.md's "Audit pass" section for the full account of this correction). Boot the domain, run ifconfig, and set these to match opentofu/modules/opnsense-edge's actual lan_network_name/wan_network_name wiring. |
|
{{WAN_IPADDR}} / {{WAN_SUBNET_BITS}} / {{WAN_GATEWAY}} |
Pending D-100/D-101 | The "simulated ISP uplink" network's real addressing isn't assigned yet (NetBox-pending). | |
{{LAN_IPADDR}} / {{LAN_SUBNET_BITS}} |
Pending a design decision | WHICH plane(s) OPNsense's LAN interface actually serves (metal-admin? provider-public? something else?) is not fully specified in the buildout design as read this session -- confirm before filling this in, don't assume. | |
{{MIRROR_SYNC_PROTOCOL}} / {{MIRROR_UPSTREAM_NET}} / {{MIRROR_SYNC_PORT}} |
Pending -- mirror software not chosen | D-107 requires the per-DC artifact mirror's own upstream sync as one of exactly two allowed WAN egress paths (the other is NTP), but doesn't specify which mirror software (apt-mirror? aptly? a generic reverse proxy?) -- the port/protocol depend on that choice. Tooling gap register item 3 territory. | |
{{ROUTE1_NETWORK}}/{{ROUTE1_GATEWAY}}/{{ROUTE1_DESCR}}, {{ROUTE2_*}} |
Optional, pending DC2 CIDR assignment | At most 2 static routes needed per the known topology (a peer-DC replication-plane route at DC1/DC2; an Office1-management route). Leave a slot's *_NETWORK var unset to omit it entirely -- scripts/opnsense-render-config.sh drops an unset slot rather than emitting an empty/invalid <route>. DC2's own CIDRs aren't assigned yet (D-101 open item), so DC1's route to DC2 can't be filled in until then. |
gateways.gateway_item is new versus the stock sample (which only has an implicit DHCP-derived gateway) -- required because the WAN side here is a static "simulated ISP uplink," not DHCP, and staticroutes.route.gateway must reference a named gateway object (confirmed from the real Route.xml model: gateway is a JsonKeyValueStoreField needing "a valid gateway from the list"). Named WAN_GW -- change consistently in both places if you rename it.unbound/nat/rrd/legacy <filter> sections are left exactly as the real stock sample ships them -- minimal, working defaults, not independently redesigned.Write the actual, final, per-site config.xml files (Office1/DC1/DC2) -- that needs the pending values above filled in with real ones, which in turn needs Stage 0 ratification (D-100/D-101/D-107) and a real boot to measure vtnetN assignment. This delivery is the mechanism (template + a tested renderer), consistent with everything else built this session: parameterized and reusable, not three files with invented IP addresses.