OPNsense High Availability with CARP: Active-Passive Failover
Configure OPNsense HA using CARP virtual IPs and pfsync state synchronization for sub-second firewall failover — step-by-step for a two-node homelab or
OPNsense supports active-passive HA using CARP (Common Address Redundancy Protocol) for virtual IPs and pfsync for connection state synchronization. When the primary node fails, the secondary takes over quickly with existing TCP sessions intact.
Before committing to this: HA is genuinely useful, but it roughly doubles your hardware, adds real configuration complexity, and introduces its own failure modes (split-brain, config drift, asymmetric routing). For most homelabs, a cold spare with a tested config backup recovers in minutes and is far simpler. Build CARP HA when you have services that genuinely cannot tolerate a multi-minute outage during a reboot or hardware failure — and when you can dedicate two near-identical boxes plus a dedicated sync link. If that’s you, read on; the payoff is sub-second, state-preserving failover.
A critical prerequisite people miss: CARP needs more than one usable IP on the WAN side. Your ISP must give you either a small static subnet (so primary, secondary, and the CARP VIP each have an address) or you must terminate the public IP on an upstream device and run CARP on a private transit network behind it. A single dynamic DHCP WAN address from a consumer ISP cannot do classic WAN CARP — plan the addressing before touching the GUI.
Architecture
ISP → [CARP VIP on WAN] → Primary OPNsense ←→ pfsync ←→ Secondary OPNsense
↓
[CARP VIP on LAN] → Managed Switch → LAN
Both nodes have:
- WAN interface (real IPs from ISP — you need two IPs or VLAN)
- LAN interface
- SYNC interface (dedicated link between nodes for pfsync + config sync)
Hardware
Two identical or compatible units. Common homelab pairs:
- Two Protectli FW4C units
- Two Topton N5105 mini-PCs with identical NIC cards
The sync interface needs at least a direct cable (modern NICs auto-MDIX, so a straight cable is fine) or a dedicated switch port/VLAN between the nodes. Keep pfsync off shared production links — a flooded LAN that delays state sync will cause failovers to drop existing connections, defeating the point.
NICs and ordering matter: both nodes should present interfaces with the same logical roles (WAN/LAN/SYNC). They don’t have to be identical hardware, but mismatched NIC counts or driver quirks make config sync fragile. Identical or near-identical units save hours of debugging.
Step 1: Network addressing plan
| Node | WAN IP | LAN IP | SYNC IP |
|---|---|---|---|
| Primary | 203.0.113.2/30 | 192.168.1.2/24 | 172.16.0.1/30 |
| Secondary | 203.0.113.3/30 | 192.168.1.3/24 | 172.16.0.2/30 |
| CARP VIP WAN | 203.0.113.4 | — | — |
| CARP VIP LAN | — | 192.168.1.1 | — |
Step 2: Configure the primary node
Create CARP virtual IPs
Interfaces → Virtual IPs → Add:
- Type: CARP
- Interface: WAN
- IP address: 203.0.113.4/30
- Virtual IP password: (shared secret, same on both nodes)
- VHID group: 1
- Advertising frequency: Base 1 / Skew 0 (primary always advertises faster)
Repeat for LAN CARP VIP.
Enable pfsync
Interfaces → Assignments → add the SYNC interface. Then:
System → High Availability → Settings:
- Synchronize states: ✓
- Synchronize interface: SYNC
- Synchronize peer IP: 172.16.0.2
Configure firewall ↗ rule for pfsync traffic
On the SYNC interface, allow pfsync protocol from 172.16.0.2.
Step 3: Configure the secondary node
Mirror the interface configuration with the secondary IPs. In HA settings:
- VHID Skew: 100 (secondary advertises slower — primary wins by default)
Enable XMLSync to push config changes from primary to secondary: System → High Availability → Settings → Synchronize config to IP: 172.16.0.2
Step 4: Verify failover
# On a LAN client, ping the CARP LAN VIP continuously
ping 192.168.1.1
# Reboot the primary
# Observe: ping continues after ~1 second gap
# Secondary takes over the CARP VIP
Check System → High Availability → Status on both nodes to confirm MASTER/BACKUP state. A correct setup shows the primary as MASTER for every CARP VIP and the secondary as BACKUP for every one. Mixed states (some VIPs MASTER on each node) indicate a VHID, password, or subnet mismatch.
Also test the realistic failure modes, not just a clean reboot:
- Pull the WAN cable on the primary — CARP should fail over if you’ve enabled interface monitoring; a primary that stays MASTER with a dead WAN is a classic misconfiguration.
- Power-kill the primary (not graceful) — confirms the secondary promotes without a clean CARP demotion message.
- Recover the primary — by default it preempts and reclaims MASTER. Decide whether you want that (fast return to normal) or prefer to disable preemption to avoid a second brief blip; set this consciously.
Common pitfalls
- Both nodes showing MASTER (split-brain) — pfsync/CARP advertisements aren’t reaching the peer. Check the SYNC (and WAN/LAN) firewall rules allow the
carpandpfsyncprotocols, and that VHID + virtual-IP password match exactly on both nodes. - Sessions not surviving failover — pfsync not enabled, the sync interface mismatched, or sync latency too high because pfsync shares a congested link. Give it a dedicated interface.
- Config sync not working — verify the HA “Synchronize config to IP” points at the secondary’s SYNC IP, that the remote user/password (or API key) is correct, and that the secondary’s GUI is reachable on the sync network. Sync is one-directional: only ever edit the primary.
- Asymmetric routing / states not matching — both nodes must use the CARP VIPs as the gateway/source for outbound and as the address clients target; mixing real and virtual IPs in NAT/outbound rules breaks state continuity on failover. Set Outbound NAT to translate to the CARP VIP, not the interface address.
- DHCP/Unbound not failing over — enable DHCP failover (or static leases) and ensure the resolver is configured identically; clients pointed at a node-specific IP lose DNS when that node dies. Point clients at the CARP VIP.
Verification checklist
After a failover test, confirm: a continuous ping to the LAN CARP VIP recovered within ~1–2 seconds; an in-progress download/SSH session survived (proves pfsync state transfer); the Status page shows the new MASTER; and after the old primary returns, state is consistent again. Document the expected behavior so the next person doesn’t mistake normal preemption for a fault.
When not to deploy CARP HA
If your ISP only provides a single dynamic IP and you can’t run CARP on a private transit segment, classic WAN HA isn’t viable — don’t force it. If your uptime requirement is “a few minutes of downtime during a rare reboot is acceptable,” a tested config backup plus a cold/warm spare is dramatically simpler and has fewer ways to fail. HA adds value specifically when unattended, sub-second, state-preserving failover is a hard requirement and you can commit the second box and a dedicated sync link to get it.
Coming from pfSense? pfSenseLab ↗ has a CARP comparison between OPNsense and pfSense implementations.
Related
OPNsense Multi-WAN Failover with Gateway Groups
Configure two ISP uplinks on OPNsense with gateway groups for automatic failover or load balancing: monitoring, NAT, DNS, and pitfalls that break it.
OPNsense vs pfSense for Homelab: Which Firewall OS Wins in 2026?
A practitioner's comparison of OPNsense and pfSense for homelab use — update cadence, licensing, IDS/IPS, VPN support, and when to pick each.
Zenarmor (Sensei) on OPNsense: Free NGFW Setup and Tuning
Install and configure Zenarmor (formerly Sensei) on OPNsense for application-aware filtering, web category blocking, and live traffic analytics — what the