Enrollment and identity
Enrollment is how a new firewall gets its own identity in pfCentral. It happens once per firewall. After that, the firewall uses the identity every time it connects.
The design has one goal: a person only ever handles a short-lived, single-use token. The long-term secrets are created by the server and travel straight to the firewall.
The sequence
Section titled “The sequence”Step through it, or let it play:
- 1. You add the device
In Devices → Add device you enter the firewall's hardware ID (SMBIOS UUID) and a name. The device now exists, waiting for enrollment.
- 2. pfCentral gives you a one-time token
The token works once, expires, and only works for that UUID. pfCentral stores a hash of it, never the token itself.
- 3. You give the token to the firewall
Paste it in Services → pfCentral → Settings, or pass it to the install script. This is the only secret a person ever handles.
- 4. The agent trades the token in
Over HTTPS the agent sends the token and its UUID to /enroll. pfCentral checks both and burns the token so nobody can use it again.
- 5. The agent gets its long-term credentials
pfCentral returns a per-device connect-secret and the shared sentinel credentials. The agent saves them on the firewall with owner-only permissions.
- 6. The agent dials NATS
It connects outbound to port 24222 and presents the sentinel credentials, its UUID and its connect-secret.
- 7. NATS asks pfCentral
NATS does not decide by itself. It forwards the login to pfCentral (the authorization callout), which checks the secret and that the device is approved and not suspended.
- 8. pfCentral signs a short-lived pass
The pass (a JWT) allows only this device's own subjects and expires. Nothing durable to steal or revoke on the broker.
- 9. The firewall is online
From now on every reconnect repeats only the last four steps. The token is never needed again.
Two phases
Section titled “Two phases”Enroll (once). The agent sends the bootstrap token and its UUID to POST /enroll over the web port. pfCentral checks the token, burns it, marks the device enrolled and approved, and returns two things:
- a connect-secret, unique to this device;
- the sentinel credentials, a shared login that lets agents reach the authorization callout.
Connect (every time). The agent connects to NATS on port 24222 with the sentinel credentials, its UUID and its connect-secret. NATS asks pfCentral (the callout) whether to admit it. pfCentral checks the secret and signs a pass that allows only pfsense.<uuid>.> for one hour. When the pass expires, NATS drops the connection and the agent reconnects within seconds, getting a fresh pass.
Bootstrap tokens
Section titled “Bootstrap tokens”| Made by | Bound to | Lifetime | Use it when |
|---|---|---|---|
| Add device in the UI | One UUID | 1 hour | You know the firewall’s UUID. Recommended. |
pf-central admin enroll token on the server | Any device in the tenant | --ttl, default 1 hour | Scripted or offline installs, or re-enrolling a device that is already enrolled. |
POST /api/devices/bootstrap-token | Any device in the tenant | 1 hour | Automation through the API. |
All tokens are single-use. pfCentral stores only a hash of each token. Generating a new UI token for a device cancels the older one.
What is stored where
Section titled “What is stored where”| Item | On the firewall | On the server |
|---|---|---|
| Bootstrap token | Until enrollment, in the package settings | A hash only, then marked used |
| Connect-secret | /usr/local/etc/nats-agent/connect.secret, mode 0600 | A peppered hash in PostgreSQL |
| Sentinel credentials | /usr/local/etc/nats-agent/sentinel.creds, mode 0600 | state/nats/users/sentinel.creds |
| NATS CA certificate (TLS only) | /usr/local/etc/nats-agent/ca.crt | state/nats/tls/ca.crt |
| Hourly pass (JWT) | In memory | Not stored |
The connect-secret hash uses the token pepper (PFCENTRAL_TOKEN_PEPPER_*). If you change the pepper without keeping the old one, no device can log in. See Rotate certificates and secrets.
Device states
Section titled “Device states”┌──────────────┐ Add device ┌──────────────────────┐ agent enrolls ┌──────────┐│ not in │ ────────────▶ │ Awaiting enrollment │ ──────────────▶ │ Enrolled ││ pfCentral │ │ (token pending) │ │ │└──────────────┘ └──────────────────────┘ └────┬─────┘ ▲ │ │ Delete device │ └─────────────────────────────────────────────────────────────────────┘Enrolled devices are online while their heartbeats arrive and offline when they stop. Enrollment approves the device automatically; there is no separate approval step.
Re-enrolling a firewall
Section titled “Re-enrolling a firewall”You re-enroll when the firewall’s credential files are lost, for example after a reinstall.
- From the firewall: paste a new token in Services → pfCentral → Settings and click Save. The package deletes the old secret and sentinel files, restarts the agent, and the agent enrolls again. The server replaces the stored secret.
- Getting a token for an enrolled device: the UI does not offer one for a device that is already enrolled. Use
pf-central admin enroll token, or delete the device and add it again.
Revoking a firewall
Section titled “Revoking a firewall”Delete the device in More → General Setup → Danger zone. This deletes its connect-secret, so the next connection attempt fails. The current hourly pass stays valid until it expires, so the agent can stay connected for up to an hour. To cut it off at once, also stop the agent on the firewall or block its traffic. See Suspend or retire a firewall.