Runbook 02 — OPNsense install + base config¶
Goal: install latest stable OPNsense on the VM from runbook 01, get GUI access on the MGMT-bound management IP, and apply base system settings + hardening + the virtio tunings. No zone VLANs yet (that's runbook 03).
Prereqs: runbook 01 validated (VM boots the installer; vtnet0=LAN trunk,
vtnet1=WAN).
1. Install¶
At the installer login prompt, log in as installer / opnsense (or root
/ opnsense on older images) to launch the guided installer.
- Keymap: default.
- Install (UFS) — the Proxmox host datastore is ZFS, so guest ZFS would be ZFS-on-ZFS: double ARC (wasted RAM on a small firewall) + write amplification, and on a single guest disk ZFS only detects corruption, can't repair it — your host pool already detects and repairs the zvol. Use UFS (SU+J) and let the host provide integrity/compression/snapshots.
- Rollback (the reason ZFS boot environments are nice) is covered host-side:
qm snapshot 9140 pre-updatebefore a firmware update, plus the config-XML backup (§7). (If you specifically want in-guest boot environments and have RAM to spare, ZFS is fine — but cap the guest ARC viavfs.zfs.arc_max.) - Set the root password (use a strong one; store in your password manager).
- Complete, remove the ISO, reboot:
# on the Proxmox node, detach the installer media so it boots from disk qm set <vmid> --ide2 none
2. Assign interfaces + management IP (console)¶
At the OPNsense console menu:
- Option 1 — Assign interfaces.
- VLANs now? no (we do VLANs in the GUI, runbook 03).
- WAN =
vtnet1 - LAN =
vtnet0 - (no optional interfaces yet) → confirm.
- Option 2 — Set interface IP address → LAN:
- IPv4 via DHCP? no
- IPv4 address:
10.20.10.1, subnet24— this is the MGMT zone gateway. The untagged LAN carries this address only until the MGMT VLAN (tag 10) is created in runbook 03; you then move the address onto the tagged MGMT interface and the untagged LAN is removed. - upstream gateway: none (blank)
- IPv6: none
- Enable DHCP server on LAN?
no(DHCP is per-VLAN via Kea, runbook 04) - Revert to HTTP for the web GUI? no (keep HTTPS)
- WAN — DHCP transit + the one WG-admin public IP: the ISP router stays inline and routes your static public block to OPNsense (it does not NAT those). So:
- Leave WAN IPv4 = DHCP — it takes a private transit lease (e.g.
10.1.10.x); the gateway is auto-namedWAN_DHCP(10.1.10.1). Use that name wherever the runbooks sayWAN_GW. Set a static DHCP reservation on the router so this WAN IP never changes. - Add only
.69as an IP Alias Virtual IP on WAN (Interfaces → Virtual IPs → + → mode IP Alias, interface WAN). This is the WG admin endpoint address (runbook 07) — the single inbound exception on the Comcast link. Hold.65–.68in reserve (unassigned) for future use. - IPv6: None (IPv4-only — see §6 "Turn off IPv6").
Home serves no public services. Under the edge/origin design (CLAUDE.md; runbook 17) the public-facing layer lives on remote VPS edges and reaches home over outbound-dialed WireGuard tunnels — which need no WAN VIP or port-forward (home initiates them). The only inbound on the Comcast link is the WG admin dial-in on
.69:51820. So there are no service IP-Aliases here, no80/443/53/22forwards — just the one.69VIP. (.65–.68stay reserved in case a future need genuinely requires another inbound address.)
3. First GUI login¶
From a client on the MGMT segment (or a host temporarily attached to the LAN
bridge), browse to https://10.20.10.1 (accept the self-signed cert). Log in
as root. Skip/complete the setup wizard quickly — we set everything explicitly
below.
In the wizard's LAN step, leave "Enable DHCP server" UNCHECKED and keep the LAN IP
10.20.10.1. Per-VLAN DHCP (Kea) comes in runbook 04; the untagged LAN never runs DHCP.
4. System settings¶
System → Settings → General
- Hostname: fw01 (or keep opnsense) · Domain: ${domain}
- Time zone: America/Chicago
- DNS servers: 9.9.9.9, 1.1.1.1 (each once — no duplicates) · leave
"use gateway" = none for now (revisit in runbook 05 so DNS follows policy).
- Uncheck "Allow DNS server list to be overridden by DHCP/PPP on WAN" (we control
DNS via Unbound).
- Prefer IPv4 over IPv6: on — IPv4-only build; this makes the firewall itself
prefer v4 (the GUI counterpart of the fleet's gai.conf).
System → Settings → Administration
- Web GUI: keep HTTPS; port 443 (clean default). Optionally regenerate a
self-signed cert now; a proper cert comes with ACME in runbook 09.
- SSH (hardening) — row labels on this page: Secure Shell Server /
Root Login / Authentication Method:
- Enable Secure Shell: on
- Permit root user login: OFF
- Permit password login: OFF (key-only)
- Listen Interfaces: leave default for now; we scope SSH to MGMT in runbook 06.
- (There is no "Login Group" field on this page in 26.1 — SSH access is
governed by the user's group/privileges + login shell, set on the user below.)
- Before you lock yourself out: create an admin user with an SSH key first —
System → Access → Users → Add — group membership admins, paste your
key into "Authorized Keys". For key SSH login the user also needs a
Login shell set (e.g. /bin/sh); a shell isn't needed for GUI-only. Test
key login, then the password/root toggles above are safe.
System → Settings → Cron — defaults fine. NTP is under Services → Network Time (not System → Settings) — the NTP pool is already set by default.
5. Plugins + firmware¶
System → Firmware → Status → Check for updates → update to the latest stable, reboot if prompted.
System → Firmware → Plugins — install (if a plugin isn't listed, click the
"Click to view the community plugins." link first to reveal community plugins):
- os-qemu-guest-agent (pairs with --agent enabled=1 from runbook 01)
- os-acme-client (optional — only for the firewall's own GUI cert via
DNS-01; the origin Caddy does its own ACME internally, runbook 09)
Note: no
os-haproxyplugin — the reverse proxy is the internal origin Caddy (runbook 09), which handles its own Let's Encrypt certs (DNS-01). The firewall port-forwards nothing for it: public traffic reaches the origin Caddy over the edge WireGuard tunnels (runbook 17), not WAN.
After install, Services → Qemu Guest Agent → enable/start (or it auto-starts).
Confirm on Proxmox: qm agent <vmid> ping returns nothing/success and the GUI
shows the guest IP.
6. Virtio tunings (required for stable virtio under KVM/Proxmox)¶
Interfaces → Settings: - Disable hardware checksum offload: ON (exact labels use "offload", not "offloading") - Disable hardware TCP segmentation offload: ON - Disable hardware large receive offload: ON - VLAN Hardware Filtering: it's a dropdown — select "Disable VLAN Hardware Filtering" (safe for virtio) - Turn off IPv6: CHECKED — IPv4-only build (26.1 label; help text: "If checked, IPv6 interface configuration will be ignored and all forwarding traffic will be blocked. Use with care."). This single box is the master IPv6 off-switch — it overrides per-interface IPv6 settings and blocks all IPv6 forwarding, so the per-interface "IPv6 = None" (runbook 03) becomes moot/tidy. Don't run RA/DHCPv6.
Save → reboot to apply cleanly.
7. Back up the clean base¶
System → Configuration → Backups → Download. Keep this "base" config as a known-good restore point. (Do not commit it to this git repo — it will start accumulating secrets.)
Validation¶
- [ ] GUI reachable at
https://10.20.10.1; root + new admin (key) both work. - [ ]
Permit root loginandpassword loginare off for SSH; key login asuserworks. - [ ] Firmware on latest stable; the plugins installed; guest-agent answers
qm agent <vmid> ping. - [ ] Interfaces → Settings shows the 3 "Disable hardware … offload" options checked.
- [ ] LAN =
10.20.10.1/24, no DHCP on LAN; WAN has its transit lease + gateway up; you can ping9.9.9.9from Interfaces → Diagnostics → Ping.
Then → runbook 03 (interfaces + VLANs).