Skip to content

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.

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.com to 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.

RouteTokenBest for
A. UI token + one commandBound to one UUIDA few firewalls; the safest
B. Install, then paste in the pfSense GUIBound to one UUIDPeople who prefer the pfSense GUI
C. Scripted rolloutUnbound, from CLI or APIMany firewalls, configuration management
  1. On the firewall: kenv smbios.system.uuid. Copy the UUID.

  2. In pfCentral: Add, paste the UUID and a name, then Add & generate token. Copy the token (valid one hour).

  3. 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
Add device: UUID in, one-time token out.
  1. Install with no settings: fetch -o - https://github.com/danielmichaels/pf-central-artifacts/releases/latest/download/install.sh | sh
  2. Make a token in pfCentral as in route A.
  3. 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.

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.

Terminal window
docker compose exec pf-central pf-central admin enroll token --ttl 4h

Run 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.

Then run the installer on each firewall with its own token, from your configuration management tool. An Ansible example:

enroll.yml
- 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_]+') }}
sh

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.

VariableDefaultMeaning
NATS_URLnats://127.0.0.1:24222Where 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_URLrelease URLPackage to install. For mirrors.
PFCENTRAL_BINARY_URLrelease URLAgent 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.

WhereHealthy
pfSense Services → pfCentral → StatusHealthy — connected & enrolled; credential scope pfsense.<uuid>.>
pfCentral left railThe device is online with live CPU and memory
Firewall log /var/log/nats_agent.logNo 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.

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.

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:

Terminal window
fetch -o /tmp/install.sh https://mirror.example.internal/pf-central/install.sh
PFCENTRAL_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.sh

In Services → pfCentral → Settings, set Binary Source to Custom URL with your mirror, so Download & Restart also uses it.

  • 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.