Skip to main content

Configuration Reference

Look up every setting pfSense Actions reads, its default, when it takes effect, and how it's validated.

How Settings Apply

  • Every start — PORT, DATA_DIRECTORY, ADMIN_WEBAUTHN_RP_NAME, LOG_LEVEL, and LOG_TIME take effect each time the service starts.
  • Only when nothing is saved — The deprecated PFSENSE_* values are bootstrap values. They fill the controller database only while nothing of their kind is saved yet, and the service still validates them at every start.
  • Empty values — An empty string counts as unset, and every variable can be left empty.

info

None of these values are needed to start. A new installation prints a setup code in its log, and you set up the administrator account, the pfSense connection, and notifications in the operations console.

API Environment Variables

These go in apps/api/.env for a source run. For Docker, add them under environment in compose.yml.

VariableDefaultDescription
PORT22603Port for the HTTP listener, from 1 to 65535. A warning is logged when it's unset, and the container fixes it at 22603.
DATA_DIRECTORY.data in the working directoryFolder for the controller database and the generated key in keys/installation.key. The container fixes it at /data.
ADMIN_WEBAUTHN_RP_NAMEpfSense ActionsName shown in passkey prompts, up to 64 characters.
LOG_LEVELEvery levelwarn or error hides the levels below it. Any other value, including auto, debug, and info, logs every level.
LOG_TIMEfalsetrue adds an ISO 8601 timestamp to each log line.
NODE_ENVSet by the scriptsproduction in the container and npm run prod, and development in npm run dev. Express shows less error detail in production.
  • pfSense Actions works out its public address from each request, so there's no setting for it. Passkeys are tied to the hostname they were added on, as described in HTTPS Reverse Proxy.

Deprecated Variables

These still work, but the console replaces them, so it's recommended to leave them unset.

  • PFSENSE_* — When they're set and no connection is saved yet, or its password or private key was removed, pfSense Actions imports them as the connection on its next start, without testing them. Change the connection on the pfSense Connection page instead.
  • Warnings — Every start logs a WARN line while any of them is set, saying whether it was imported or ignored.
  • Removal — A later major version may stop reading them.
VariableDefaultDescription
PFSENSE_SSH_IPNoneThe firewall's IPv4 or IPv6 address, not a hostname.
PFSENSE_SSH_PORT22SSH port, from 1 to 65535.
PFSENSE_USERNAMENoneSSH username.
PFSENSE_PASSWORDNoneSSH password.
PFSENSE_PRIVATE_KEYNoneSSH private key contents, not a path, without a passphrase. When both are set, the password is used.

Set PFSENSE_SSH_IP, PFSENSE_USERNAME, and PFSENSE_PASSWORD or PFSENSE_PRIVATE_KEY together, or leave all of them empty, because partial values stop the service from starting.

Compose and Container Variables

The root .env file sets these values for compose.yml, and every one is optional.

VariableDefaultDescription
PFSENSE_ACTIONS_PORT22603Host port, published on every IPv4 and IPv6 address.
PUID1000User ID the service runs as, from 1 to 2147483647.
PGID1000Group ID the service runs as, from 1 to 2147483647.
TZUTCTime zone name from the image's time zone database.
S6_READ_ONLY_ROOT0Passed through to s6-overlay. Compose doesn't make the container's root filesystem read-only.
  • The container sets DATA_DIRECTORY to /data, PORT to 22603, and NODE_ENV to production.
  • The root .env also has NODE_ENV, LOG_LEVEL, and LOG_TIME from its sample, but Compose doesn't pass them into the container.
  • The Compose file turns on IPv6 for the container's network, so the rate limits and the sign-in limit count each IPv6 client by its own address. Docker Engine 27 or later picks the IPv6 subnet on its own, and on a host without IPv6, you can delete the networks block. IPv6 addresses are often reachable from the internet, so it's recommended to check that your router or host firewall blocks inbound connections to the port.

Encryption Key

pfSense Actions keeps its encryption key in keys/installation.key in the data folder, which is /data/keys/installation.key in the container, and generates it there on the first start.

RuleDetail
FormatExactly 64 hexadecimal characters, with surrounding whitespace trimmed. A file in any other format stops startup.
Missing filepfSense Actions makes a new key and removes the secrets the old one sealed: the saved pfSense password or private key, the authenticator app, and the secret fields of each notification destination.
MatchingThe key file has to belong to this database, and startup stops when it doesn't.
Generated fileCreated readable only by the service's user, in a folder only that user can open.

Backup and Recovery covers a missing key file and one that doesn't match.

npm Scripts

CommandDescription
npm run dev --workspace pfsense-actions-app-apiRuns the API with tsx watch, loading apps/api/.env, and the console with Vite at http://localhost:5174/admin/.
npm run build --workspace pfsense-actions-app-apiCompiles the API into apps/api/build and the console into apps/api/build/admin.
npm run prod --workspace pfsense-actions-app-apiRuns node build/index.js without loading apps/api/.env.
npm run deploy:containerRuns docker compose up --build --detach.

Limits

LimitValue
JSON body size64 KB
Action route rate limit3 requests per 10 seconds per client address
/api/v1 rate limit120 requests per minute per client address
Console sign-in limit10 failed attempts per 15 minutes per client address
Setup screen limit10 wrong codes per 15 minutes per client address
Setup code30 minutes, and one use
count on the ping route1 to 10 ping attempts, 5 packets each
Browser session24 hours from sign-in
Code step after a password5 minutes, and 5 wrong codes
Authenticator setup10 minutes
Passkey prompt60 seconds
SSH connection attempt20 seconds
Activity log250 events stored and shown
Notification destination name80 characters, different from every other destination's name regardless of letter case
Notification send10 seconds, with no retries
Scheduled checkEvery 5 minutes, with pfSense can't be reached after 2 failures in a row
Sign-in locked alertOnce per client address per 15 minutes