A Home Assistant integration for pfSense® firewalls, built on the pfSense REST
API v2 (pfSense-pkg-RESTAPI). It surfaces live system, interface, gateway,
DHCP and VPN telemetry as entities, and lets you drive firewall rules, NAT
rules, services, aliases and routing from Home Assistant.
Origin. This project started as a fork of DonTranQuiL/Pfsense-pro, but has since been extensively rewritten — the XML-RPC client was replaced with a native async REST API v2 client and most of the integration was reworked, with the help of Claude Cowork. It has been de-forked from the upstream repository so that pull requests don't get opened against DonTranQuiL/Pfsense-pro by mistake. It is now maintained as a standalone project.
- pfSense 26.07 or newer with the REST API v2 package installed and enabled (System › Package Manager, then System › REST API).
- An API key created at System › REST API › Keys, tied to a user that has
the privileges the integration needs.
WebCfg - All pagesgrants everything; a locked-down user needs read access to system/interface/gateway/service/DHCP status plus write access to whatever you intend to control (firewall rules, aliases, services, routing). - The API's base URL, including its port (the REST API commonly runs on a
non-standard port such as
8444, separate from the web UI).
This integration speaks REST v2 only. pfSense installs without the REST API package, or older than the version it requires, are not supported.
-
In HACS, open the three-dot menu → Custom repositories.
-
Add the repository URL and set the category to Integration:
https://github.com/nolsen311/Pfsense-REST -
Download pfSense Pro, then restart Home Assistant.
-
Go to Settings → Devices & Services → Add Integration and search for pfSense.
- Download the latest release.
- Copy the
custom_components/pfsensefolder into your Home Assistantconfig/custom_components/directory. - Restart Home Assistant and add the integration as above.
When you add the integration you are asked for:
| Field | Notes |
|---|---|
| URL | Base URL of the REST API, with scheme and port, e.g. https://pfsense.lan:8444. Any path is ignored. |
| API key | The key value from System › REST API › Keys. Sent as the x-api-key header. |
| Verify SSL certificate | Turn off for a self-signed certificate. |
| Firewall Name | Optional friendly name; defaults to hostname.domain. |
After setup, Configure exposes:
- Scan Interval – how often the main state poll runs (default 30 s).
- Enable Device Tracker – adds a second, slower poll of the ARP table and a device picker so you can track specific MAC addresses.
- Device Tracker Scan Interval / Consider Home – timing for the tracker.
Most entities are created disabled by default — enable the specific ones you want in the entity settings.
- System: WAN IP address, CPU usage %, CPU count, memory usage %, swap usage %, memory-buffer usage %, system temperature, load average (1 / 5 / 15 min).
- DHCP: total leases, online leases, idle/offline leases.
- Per interface: link status, in/out byte and packet counters (passed traffic) plus their kB/s and packets/s rates, interface errors, collisions.
- Per gateway: status, RTT delay, jitter (stddev), packet loss %.
- Per OpenVPN server: connected client count, total bytes in/out plus rates.
- Per CARP virtual IP: MASTER / BACKUP status.
- One per firewall rule – toggles the rule's
disabledflag and applies the change. Keyed by the pfSense internaltrackervalue. - One per NAT rule (port forward and outbound) – same, keyed by the rule's
created_time. - One per service – start / stop a daemon (
unbound,haproxy,openvpn, …).
- CARP Status – whether CARP is enabled and not in maintenance mode.
- Reboot Router, Halt Router, Reset State Table – one-press equivalents of the matching services.
- One
device_trackerper MAC address you select in the options flow, marked home/away from the pfSense ARP table.
- Firmware Updates Available – read-only. The REST API exposes no base-system "update available" signal or progress-tracked upgrade, so this entity reports status only and cannot install.
| Service | What it does |
|---|---|
pfsense.update_alias |
Add or remove an address from a host alias, apply the ruleset, and optionally kill matching states so the change takes effect immediately. |
pfsense.start_service / stop_service / restart_service |
Control a pfSense daemon by name. |
pfsense.set_default_gateway |
Set the IPv4 or IPv6 default gateway and apply routing. |
pfsense.kill_states |
Drop firewall states for a source (and optional destination). |
pfsense.reset_state_table |
Flush the entire state table. |
pfsense.send_wol |
Send a Wake-on-LAN packet from a pfSense interface. |
pfsense.system_reboot / system_halt |
Reboot or halt the firewall. |
pfsense.exec_command |
Run a shell command via /api/v2/diagnostics/command_prompt (output is truncated at 1024 characters). |
Each service is routed through an integration entity, so calls take an
entity_id of any pfSense entity (used only to select the target firewall).
alias: Isolate suspicious client
trigger:
- platform: state
entity_id: binary_sensor.perimeter_intrusion_alert
to: "on"
action:
- service: pfsense.update_alias
data:
entity_id: binary_sensor.pfsense_carp_status
alias_name: Isolation
address: "{{ state_attr('device_tracker.suspicious_client', 'ip') }}"
action: add
kill_states: truealias: Workstation VPN redirect (morning)
trigger:
- platform: time
at: "08:00:00"
action:
- service: pfsense.update_alias
data:
entity_id: binary_sensor.pfsense_carp_status
alias_name: vpn_clients
address: "192.168.1.120"
action: add
kill_states: trueThe alias must already be referenced by a firewall or NAT rule in pfSense; Home Assistant only changes which addresses are in it.
The integration is fully asynchronous. A DataUpdateCoordinator polls a set of
read-only status endpoints concurrently each cycle:
GET /api/v2/status/system CPU / memory / temperature / load / identity
GET /api/v2/status/interfaces link state and traffic counters
GET /api/v2/status/gateways gateway RTT / loss / status
GET /api/v2/status/openvpn/servers
GET /api/v2/status/services
GET /api/v2/status/dhcp_server/leases
GET /api/v2/status/carp
GET /api/v2/firewall/virtual_ips CARP VIPs
GET /api/v2/firewall/rules , /nat/port_forwards , /nat/outbound/mappings
GET /api/v2/routing/gateways , /routing/gateway/default
GET /api/v2/system/dns , /system/hostname , /system/version
Rates (bytes/s, packets/s) are computed from consecutive polls. Successful polls are cached to disk, so a brief pfSense outage does not blank every entity.
Writes stage a change and then call the matching apply endpoint
(POST /api/v2/firewall/apply, /routing/apply), serialised so concurrent
applies cannot race. The device's unique ID is the pfSense Netgate device ID
from /api/v2/status/system.
v3 removes the XML-RPC / exec_php transport entirely. On upgrade:
- Re-authentication is required. The stored username/password is dropped and Home Assistant prompts you for an API key. Entity history is preserved (the device unique ID is unchanged).
- The URL must include the REST API port.
- Removed – no REST equivalent: the
exec_phpservice; the "Pending Notices Present" binary sensor and theclose_notice/file_noticeservices. updateentity is now read-only (no one-click firmware install).- Removed sensors – no REST data source: memory byte figures (physmem/usermem/realmem/swap totals), CPU frequency, per-filesystem usage, system boot time, per-interface blocked-traffic counters, pf state-table gauges, and pfBlockerNG block counts.
system_rebootno longer supports thefsck/rerootmodes.
Built on the groundwork of Travis Hansen (@travisghansen) and contributors to
travisghansen/hass-pfsense,
and the DonTranQuiL/pfsense-pro fork it descends from. The REST API itself is
the community pfSense-pkg-RESTAPI
project.
pfSense® is a registered trademark of Rubicon Communications, LLC (Netgate). This is an independent Home Assistant integration and is not affiliated with, endorsed by, or sponsored by Netgate.