Enroll firewalls
Enrolling a firewall has two parts: install the agent on the firewall, and give it a one-time token. You can do both in one command. This page covers every combination. For the background, see Enrollment and identity.
Before you start
Section titled “Before you start”On each firewall:
- pfSense 2.7.0 or later on amd64.
- Outbound access to the server: TCP 24222 (NATS) always, and the web port (443 behind a proxy, or 2808) during enrollment.
- Outbound HTTPS to
github.comto download the package and agent, or a local mirror (see offline installs). - A shell as root: SSH, or Diagnostics → Command Prompt.
On the server you need the admin or owner role to make tokens.
Choose a route
Section titled “Choose a route”| Route | Token | Best for |
|---|---|---|
| A. UI token + one command | Bound to one UUID | A few firewalls; the safest |
| B. Install, then paste in the pfSense GUI | Bound to one UUID | People who prefer the pfSense GUI |
| C. Scripted rollout | Unbound, from CLI or API | Many firewalls, configuration management |
A. UI token and one command
Section titled “A. UI token and one command”-
On the firewall:
kenv smbios.system.uuid. Copy the UUID. -
In pfCentral: Add, paste the UUID and a name, then Add & generate token. Copy the token (valid one hour).
-
On the firewall, as root:
Terminal window fetch -o - https://github.com/danielmichaels/pf-central-artifacts/releases/latest/download/install.sh \| NATS_URL=tls://pf.example.com:24222 \ENROLL_URL=https://pf.example.com/enroll \NATS_CA_URL=https://pf.example.com/nats-ca.crt \BOOTSTRAP_TOKEN=device_… \SITE="Sydney branch" \sh
B. Install, then paste in the pfSense GUI
Section titled “B. Install, then paste in the pfSense GUI”- Install with no settings:
fetch -o - https://github.com/danielmichaels/pf-central-artifacts/releases/latest/download/install.sh | sh - Make a token in pfCentral as in route A.
- In the pfSense GUI open Services → pfCentral → Settings, fill in NATS URL, Enroll URL and Bootstrap Token, leave NATS CA on Automatic, and click Save.
All fields are described in the pfSense package reference.
C. Scripted rollout
Section titled “C. Scripted rollout”For many firewalls, use unbound tokens: any one device can claim each token, so you do not need every UUID first. Make one token per firewall, each used once.
docker compose exec pf-central pf-central admin enroll token --ttl 4hRun it once per firewall. --ttl sets the lifetime (default 1h). The command talks to the database directly, so it works even if the web server is down.
curl -fsS -X POST https://pf.example.com/api/devices/bootstrap-token \ -H "Authorization: Bearer $PFCENTRAL_TOKEN"The token lasts one hour. Make API tokens in API Tokens in the avatar menu; see API tokens and automation.
Then run the installer on each firewall with its own token, from your configuration management tool. An Ansible example:
- hosts: pfsense gather_facts: false tasks: - name: Mint a one-time token on the pfCentral host delegate_to: pfcentral command: docker compose -f /opt/pf-central/compose.yaml exec -T pf-central pf-central admin enroll token --ttl 2h register: minted changed_when: true
- name: Install and enroll the agent raw: > fetch -o - https://github.com/danielmichaels/pf-central-artifacts/releases/latest/download/install.sh | NATS_URL=tls://pf.example.com:24222 ENROLL_URL=https://pf.example.com/enroll NATS_CA_URL=https://pf.example.com/nats-ca.crt SITE="{{ site }}" BOOTSTRAP_TOKEN={{ minted.stdout | regex_search('device_[A-Za-z0-9_]+') }} shThe installer
Section titled “The installer”install.sh installs the pfSense-pkg-nats-agent package, downloads the agent binary to /usr/local/bin/nats-agent, writes the agent’s settings, enables the nats_agent service and starts it.
| Variable | Default | Meaning |
|---|---|---|
NATS_URL | nats://127.0.0.1:24222 | Where the agent connects. Use tls:// with NATS TLS. |
ENROLL_URL | — | https://<server>/enroll. Needed to enroll. |
BOOTSTRAP_TOKEN | — | One-time token. Without it the agent waits for one in the GUI. |
NATS_CA_URL | — | Where to download the NATS CA, for tls://. Usually https://<server>/nats-ca.crt. |
SITE | — | Free-text site name, shown in pfCentral. |
PFCENTRAL_INSTALL_URL | release URL | Package to install. For mirrors. |
PFCENTRAL_BINARY_URL | release URL | Agent binary to download. For mirrors. |
The variables only apply the first time. If the package already has a NATS URL, the installer keeps the existing settings and only upgrades the package and binary. That makes it safe to run again.
Confirm enrollment
Section titled “Confirm enrollment”| Where | Healthy |
|---|---|
| pfSense Services → pfCentral → Status | Healthy — connected & enrolled; credential scope pfsense.<uuid>.> |
| pfCentral left rail | The device is online with live CPU and memory |
Firewall log /var/log/nats_agent.log | No repeated errors |
If the Status tab says Enrolled but the device is offline, the HTTP part worked and NATS did not: check port 24222 and the CA. Do not make a new token. See Troubleshooting.
Firewalls without a UUID
Section titled “Firewalls without a UUID”Some virtual machines and white-box boards report no SMBIOS UUID. The installer then uses the hostname as the device ID. A UUID-bound UI token fails for those firewalls, so use an unbound token from route C. Give such firewalls unique hostnames before you install.
Air-gapped and offline installs
Section titled “Air-gapped and offline installs”The firewall needs the package and the binary, not internet access. Host the two release files (pfSense-pkg-nats-agent.pkg and nats-agent-freebsd-amd64) on an internal web server, then:
fetch -o /tmp/install.sh https://mirror.example.internal/pf-central/install.shPFCENTRAL_INSTALL_URL=https://mirror.example.internal/pf-central/pfSense-pkg-nats-agent.pkg \PFCENTRAL_BINARY_URL=https://mirror.example.internal/pf-central/nats-agent-freebsd-amd64 \NATS_URL=tls://pf.example.internal:24222 ENROLL_URL=https://pf.example.internal/enroll \NATS_CA_URL=https://pf.example.internal/nats-ca.crt BOOTSTRAP_TOKEN=device_… \sh /tmp/install.shIn Services → pfCentral → Settings, set Binary Source to Custom URL with your mirror, so Download & Restart also uses it.
Re-enroll or move a firewall
Section titled “Re-enroll or move a firewall”- New credentials for the same firewall: make an unbound token (route C), paste it in Services → pfCentral → Settings, and Save. The package deletes the old credentials and enrolls again.
- Rebuilt firewall, same hardware: the UUID is the same. Delete the device in pfCentral, add it again, and enroll as new.
- Different hardware: it is a new device. Enroll it, then retire the old one.