pfSense API and Management Automation
A REST API transforms pfSense from a standalone firewall into a programmable infrastructure component. Instead of manual configuration through the web interface, administrators can perform operations via HTTP requests, integrate pfSense into orchestration systems, and adopt an Infrastructure as Code approach. This becomes essential in environments with dozens of devices where manual configuration of each firewall is impractical.
pfSense REST API Package
pfSense does not include a built-in REST API. Programmatic access is provided by the community package pfSense-api , which adds over 200 endpoints for system management.
Installation
The package is installed from the pfSense command line:
pkg-static add https://github.com/jaredhendrickson13/pfsense-api/releases/latest/download/pfSense-2.7.2-pkg-RESTAPI.pkgAfter installation, API settings are available under System > REST API in the web interface.
Authentication
The API supports three authentication methods:
| Method | Header | Expiration | Recommendation |
|---|---|---|---|
| Basic Auth | Authorization: Basic <base64> | Permanent | Testing only |
| API Key | X-API-Key: <key> | Permanent | Scripts and automation |
| JWT | Authorization: Bearer <token> | Time-limited | Interactive applications |
Obtaining a JWT Token
curl -X POST -H "Content-Type: application/json" \
-u admin:pfsense \
https://pfsense.example.com/api/v2/auth/jwtThe response contains a token that is then passed in the header:
curl -H "Authorization: Bearer <token>" \
https://pfsense.example.com/api/v2/firewall/rulesAPI Key Authentication
API keys are created in the web interface (System > REST API > Settings) and are bound to a user account. Key privileges are inherited from the associated account.
curl -H "X-API-Key: <your-api-key>" \
https://pfsense.example.com/api/v2/system/infoAPI Endpoints Overview
System Information
# Get system information
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/system/info
# Version and update status
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/system/versionFirewall Rules
# List all firewall rules
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/firewall/rules
# Create a new rule
curl -X POST -H "Content-Type: application/json" \
-H "X-API-Key: <key>" \
-d '{
"type": "pass",
"interface": "wan",
"ipprotocol": "inet",
"protocol": "tcp",
"source": "any",
"destination": "any",
"dstport": "443",
"descr": "Allow HTTPS inbound"
}' \
https://pfsense.example.com/api/v2/firewall/rules
# Apply changes (required after modifying rules)
curl -X POST -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/firewall/applyInterface Management
# List network interfaces
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/interface
# Update interface configuration
curl -X PUT -H "Content-Type: application/json" \
-H "X-API-Key: <key>" \
-d '{"if": "em1", "descr": "DMZ", "enable": true}' \
https://pfsense.example.com/api/v2/interfaceVPN Management
# List OpenVPN servers
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/vpn/openvpn/server
# List IPsec tunnels
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/vpn/ipsec/phase1Automation with Ansible
The pfsensible.core collection provides modules for declarative pfSense management through Ansible. The collection communicates with pfSense via xmlrpc and the PHP interface, requiring no additional package installations.
Installing the Collection
ansible-galaxy collection install pfsensible.coreExample Playbook
- name: Configure pfSense firewall
hosts: pfsense_firewalls
gather_facts: false
collections:
- pfsensible.core
tasks:
- name: Create alias for web servers
pfsense_alias:
name: web_servers
type: host
address: "10.0.1.10 10.0.1.11 10.0.1.12"
descr: "Production web servers"
state: present
- name: Allow HTTPS to web servers
pfsense_rule:
name: "Allow HTTPS to web servers"
interface: WAN
action: pass
protocol: tcp
source: any
destination: web_servers
destination_port: 443
state: present
- name: Configure DNS resolver
pfsense_dns_resolver:
enable: true
dnssec: true
forwarding: trueInventory Configuration
[pfsense_firewalls]
fw01 ansible_host=192.168.1.1
[pfsense_firewalls:vars]
ansible_connection=httpapi
ansible_httpapi_use_ssl=true
ansible_httpapi_validate_certs=false
ansible_user=admin
ansible_password=pfsense
ansible_network_os=pfsensible.core.pfsenseAutomation with Terraform
An unofficial Terraform provider for pfSense enables configuration management through declarative HCL files.
terraform {
required_providers {
pfsense = {
source = "sjafferern/pfsense"
version = "~> 0.1"
}
}
}
provider "pfsense" {
url = "https://192.168.1.1"
user = "admin"
password = var.pfsense_password
insecure = true
}
resource "pfsense_firewall_alias" "blocked_countries" {
name = "blocked_countries"
type = "network"
description = "Blocked country subnets"
entries = ["10.99.0.0/16", "10.98.0.0/16"]
}The provider is in early development. Thorough testing is recommended before using it in production environments.
PHP Shell for Programmatic Access
pfSense includes a developer PHP shell accessible via the console (option 12) or SSH. The shell allows direct reading and modification of system configuration.
Accessing the PHP Shell
Enter an option: 12
Starting the pfSense developer shell....
pfSense shell:Common Operations
// Read current configuration
parse_config(true);
print_r($config['interfaces']);
exec
// Modify configuration
$config['system']['hostname'] = "fw-prod-01";
write_config("Updated hostname via PHP shell");
execPlayback Scripts
Predefined scripts for common tasks are executed from the command line:
# From SSH or console shell
pfSsh.php playback enablesshd
pfSsh.php playback changepassword
pfSsh.php playback installpkg "Some Package"
pfSsh.php playback listpkgxmlrpc for Configuration Management
pfSense uses xmlrpc for configuration synchronization between nodes in a high-availability (CARP) cluster. The same mechanism can be used for programmatic reading and writing of configuration data.
xmlrpc is accessible at https://<pfsense-ip>/xmlrpc.php and accepts standard XML-RPC calls with Basic authentication.
The pfsensible.core collection uses xmlrpc as its primary transport for communicating with pfSense.
Backup via API
The REST API enables automated configuration backup creation:
# Download configuration via API
curl -H "X-API-Key: <key>" \
https://pfsense.example.com/api/v2/system/config \
-o config-backup-$(date +%Y%m%d).xmlAutomated Backup Script
#!/bin/sh
# Daily pfSense configuration backup via API
PFSENSE_HOST="https://192.168.1.1"
API_KEY="your-api-key"
BACKUP_DIR="/backups/pfsense"
DATE=$(date +%Y%m%d-%H%M)
curl -sk -H "X-API-Key: ${API_KEY}" \
"${PFSENSE_HOST}/api/v2/system/config" \
-o "${BACKUP_DIR}/config-${DATE}.xml"
# Remove backups older than 30 days
find "${BACKUP_DIR}" -name "config-*.xml" -mtime +30 -deleteUse Cases
Mass Deployment
When deploying multiple pfSense devices, an Ansible playbook applies a unified configuration to all nodes. A typical workflow:
- Base pfSense installation on each device
- SSH access and credential configuration
- Apply playbook with common firewall rules, VPN configuration, and DNS settings
- Apply device-specific variables (IP addresses, hostnames)
CI/CD for Firewall Rules
Firewall rules are stored in a Git repository as YAML files. When merged into the main branch, the CI pipeline applies changes via the API or Ansible:
# .gitlab-ci.yml
deploy_firewall_rules:
stage: deploy
script:
- ansible-playbook -i inventory/production firewall-rules.yml
only:
- main
when: manualAutomated Testing
After applying changes, automated checks verify configuration correctness:
# Verify accessibility after rule changes
curl -sf -o /dev/null https://pfsense.example.com/api/v2/system/info \
-H "X-API-Key: <key>" && echo "API accessible" || echo "API unreachable"Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| 401 Unauthorized | Invalid credentials or expired JWT | Verify API key or request a new token |
| 403 Forbidden | Insufficient user privileges for API | Assign required privileges in System > User Manager |
| Connection refused on API port | REST API package not installed or not running | Verify package installation and service status |
| Changes not applied | /api/v2/firewall/apply not called | Execute apply after modifying rules |
| xmlrpc timeout | Large config.xml or network issues | Increase timeout, verify network connectivity |
| Ansible module cannot find pfSense | Incorrect ansible_network_os | Set to pfsensible.core.pfsense |
Related Sections
- pfSense Custom Scripts - shellcmd, cron jobs, and PHP scripts for local automation
- pfSense Backup - manual and automated configuration backups
- pfSense High Availability - xmlrpc configuration synchronization between CARP cluster nodes