pebble.
Pebble / Docs / Operating

Migrating from OPNsense

Migrate with spare hardware. Your OPNsense router stays untouched and in service until you decide to swap the cables.

1. Export a configuration#

In OPNsense: System → Configuration → Backups → Download configuration. Leave "Encrypt this configuration file" unticked; the importer reads plain XML. The file contains secrets (WireGuard private keys, password hashes, certificates): keep it on an encrypted disk and delete it when done.

2. Import#

pebble import opnsense config-gateway-20261016.xml -o import --map wan=igb0,lan=igb1

Outputs:

File Contents
pebble.yaml translated configuration, already accepted by pebble validate
secrets-manifest.yaml each secret file the router needs, its source and status (never the value)
migration-report.md everything translated, partial, unsupported, ambiguous, dangerous, conflicting or needing verification

The importer never contacts any system and never applies anything.

3. Read the report#

Sections, most important first:

Untranslatable elements are reproduced (with secrets redacted) so nothing is silently discarded.

Supported layouts#

Feature OPNsense layouts recognised
Interfaces <interfaces> (wan, lan, optN)
DHCP legacy ISC <dhcpd>; Kea <OPNsense><Kea><dhcp4>; dnsmasq <OPNsense><dnsmasq> (best effort, from documented field names)
DNS legacy <unbound>; <OPNsense><unboundplus> (hosts, aliases, domain overrides, query forwarding, DNSBL)
Gateways <gateways> and <OPNsense><Gateways>
Aliases <OPNsense><Firewall><Alias> host, network and port aliases with literal content
Firewall <filter><rule> (interface rules); automation rules are reported, not translated
NAT <nat><rule> port forwards; outbound mode; one-to-one and NPT reported
WireGuard <OPNsense><wireguard> servers and clients

The detected layout and model versions are listed at the top of the report. All fixtures in tests/fixtures/opnsense are synthetic; please report exports from real releases that translate poorly (with secrets removed).

Semantics to be aware of#

4. Prepare the test router#

On the spare FreeBSD machine (see installation.md):

sh scripts/install.sh
pebble interfaces
cp import/pebble.yaml /usr/local/etc/pebble/pebble.yaml
vi /usr/local/etc/pebble/pebble.yaml      # check devices; set migration.interfaces_confirmed: true
install -m 0600 -o root import/keys/wg0.key /usr/local/etc/pebble/keys/   # if extracted
pebble validate && pebble plan --diff

5. Test in isolation#

Connect the test router's WAN to a spare port on your existing LAN (it will get a private WAN address — that is fine for testing) and its LAN to an isolated switch with a test client. Do not connect its LAN to your production LAN: two DHCP servers would compete.

pebble apply && pebble confirm

Then verify, from the test client:

  1. DHCP: the client gets an address, gateway and DNS server (pebble dhcp leases).
  2. DNS: local names, blocked names, external names (pebble dns test <name> on the router).
  3. NAT and Internet access: browse; pebble firewall test --in lan ....
  4. WireGuard: point a test peer (or the remote site, during a maintenance window) at the test router; pebble vpn test <peer>.
  5. Site-to-site rules: confirm allowed and denied flows.
  6. Rollback: apply a deliberately wrong SSH policy and do not confirm; check that it is restored after the rollback window.
  7. Reboot and check pebble status, pebble diagnose.
  8. Compare behaviour with OPNsense for a day if you can.

6. Switch over#

In a maintenance window, from the local console of the new router:

  1. Update remote WireGuard peers' endpoints to the new public address if it changes.
  2. Move the WAN cable from OPNsense to the Pebble router and the LAN cable to the production switch.
  3. pebble diagnose; renew a client's DHCP lease; test DNS and Internet.
  4. Keep the OPNsense box unchanged and powered off for quick fallback: swapping the cables back restores the old network.