Synchronize DHCP static mappings from pfSense to UniFi controller.
This tool automates the export of client lists from pfSense to UniFi. It reads DHCP static mappings from your pfSense DHCP table (MAC, IPv4 reservation, hostname, and description), filters by description suffix, and synchronizes them to your UniFi controller as known clients.
- Loads UniFi and pfSense credentials from environment
- Initializes NSS database for secure HTTPS connections
- Transparently verifies server certificates using NSS/NSPR
- Authenticates with pfSense API
- Retrieves DHCP static mappings
- Filters by description suffix (configurable, default:
- Wifi) - Validates MAC address format
- For each filtered client:
- Sets the MAC address
- Sets UniFi client name to pfSense description (suffix removed)
- Sets UniFi client note to pfSense hostname
- Creates new client or updates existing
- Retries failures with exponential backoff
- Batch-verifies all clients were created or updated
- Identifies UniFi clients not in pfSense sync
- Reports found orphans
- Optionally deletes orphaned clients
- Tracks success/failures
Please see the READMe.md Configuration section .
- Default:
" - Wifi" - Description: Filter clients by description suffix. Only pfSense clients whose description ends with this suffix will be synced to UniFi.
- Special Value: Use
--suffix NONEto sync all clients without filtering by suffix. - Example:
--suffix "@unifi"syncs only clients ending in "@unifi" - Example:
--suffix NONEsyncs all DHCP clients
- Default: Not set (merge mode)
- Description: Delete UniFi clients not found in pfSense. Without this flag, the sync performs a merge: adds new clients, updates existing ones, leaves others alone. With this flag, also removes clients from UniFi that don't exist in pfSense.
- Example:
--delete-orphans
Adds new clients and updates existing ones. Does not delete any existing Unifi clients.
./pfsense2unifi.py syncBy default, only clients with pfSense descriptions ending in - Wifi are synced:
./pfsense2unifi.py sync --suffix " - Wired"
./pfsense2unifi.py sync --suffix "@unifi"
./pfsense2unifi.py sync --suffix " - Home"To migrate every DHCP client without filtering by suffix:
./pfsense2unifi.py sync --suffix NONEThis is useful when migrating all clients from pfSense to UniFi, regardless of their description.
Flag: --delete-orphans
Remove clients from UniFi that weren't present in the pfSense DHCP table. By default, the sync performs a merge operation (adds new clients, updates existing ones, leaves others alone). Use this flag to also delete orphaned clients:
./pfsense2unifi.py sync --delete-orphansCombined with custom filtering:
./pfsense2unifi.py sync --suffix "@unifi" --delete-orphans./pfsense2unifi.py --help # Main help (lists subcommands)
./pfsense2unifi.py sync --help # Sync subcommand options (includes --delete-orphans)
./pfsense2unifi.py trust --help # Certificate optionsAll MAC addresses in pfSense must use colon delimiters :
✓ Valid: AA:BB:CC:DD:EE:FF, aa:bb:cc:dd:ee:ff
✗ Invalid: AABBCCDDEEFF, AA-BB-CC-DD-EE-FF, AA.BB.CC.DD.EE.FF
❌ Configuration Error: Missing required UniFi environment variables: UNIFI_NETWORK_URL, UNIFI_USERNAME, UNIFI_PASSWORD
usage: pfsense2unifi.py [-h] {sync,trust} ...
Sync DHCP reservations from pfSense to UniFi controller
...
Fetching DHCP static mappings from pfSense...
Found 12 static mappings in pfSense.
Attempting to log into UniFi Controller...
UniFi login successful.
Pre-fetching all UniFi clients...
Found 8 existing clients in UniFi.
Processing 12 pfSense DHCP mappings...
[1/12] ✓ aa:bb:cc:dd:ee:01: MyLaptop
[2/12] ✓ aa:bb:cc:dd:ee:02: MyPhone
...
Verifying clients in UniFi (batch check)...
✓ Verified 10/10 clients in UniFi
======================================================================
SYNC SUMMARY
======================================================================
Total pfSense clients retrieved: 12
- Clients with invalid MAC format: 0
- Clients filtered out (not ending in ' - Wifi'): 2
- Clients successfully created in UniFi: 8
- Clients successfully updated in UniFi (fields changed): 0
- Clients failed to add/update: 0
======================================================================
Make sure all required environment variables are set:
echo $UNIFI_NETWORK_URL $UNIFI_USERNAME $UNIFI_PASSWORD $PFSENSE_URL $PFSENSE_APIV2_KEYIf you get certificate validation errors:
Option 1: Trust the CA (recommended)
./pfsense2unifi.py trust --ca /path/to/ca.pemExpected formats: [ca_cert.pem|ca_cert.der] - or the server certificate is self-signed or self-issued
Option 2: Trust the server directly
./pfsense2unifi.py trust --server https://pfsense.example.com- Verify pfSense DHCP descriptions end with the configured suffix (default:
- Wifi) - Check MAC addresses use colon delimiters (
AA:BB:CC:DD:EE:FF) - Verify credentials have API access
- Check pfSense API key is valid and has correct permissions
- Verify both UniFi and pfSense URLs are reachable
- Check firewall rules allow access to UniFi (8443) and pfSense (443) ports
- Ensure network connectivity before running sync
- Exports only in one direction, from pfSense to Unifi, not the other way around
- IP addresses from pfSense DHCP reservations are currently not exported to Unifi. This is because the test environment doesn't have a router, and these reservations don't apply. The feature could be easily added for someone migrating from pfSense to Unifi, rather than co-existing like mine. This feature was not added due to being unable to test it.
- Tested only with pfSense+ 25.07.1, pfSense APIv2, and Unifi Network 9.5.21 GA
- Not tested with Unifi OS. No API token support as a result.
- Opnsense not supported
- See README.md for general setup and prerequisites
- See unifi_climgr.md for UniFi client and AP management