Skip to content

Configuration Reference

Firewall-Plus is configured in three places:

  • Node config.json/etc/firewall-plus/config.json on each Wings host
  • Node environment variablesFWP_*, set in the systemd unit
  • Panel admin settingsAdmin → Firewall → Settings (stored in the panel database)

Node config.json

Path: /etc/firewall-plus/config.json (override with FWP_CONFIG). Validated with a strict schema at startup — the service refuses to boot on invalid values.

KeyTypeDefaultDescription
panelUrlstring (URL)URL of your Pterodactyl panel. Informational/identification use by the daemon.
apiEndpointstringLegacy alias for panelUrl. Use panelUrl going forward.
listenAddressstring127.0.0.1Bind address. Keep loopback or an internal interface in production — never 0.0.0.0 without a populated allowedIps.
listenPortint 1024–655358472Bind port for the REST API.
allowedIpsstring[][]IP/CIDR whitelist (IPv4 and IPv6) allowed to call protected routes. Your panel's egress IP must be in here when binding beyond loopback.
trustProxyboolfalseSet true only behind a trusted reverse proxy (nginx/caddy). When false, the direct peer IP is used, so the whitelist can't be bypassed with a spoofed X-Forwarded-For.
allowEmptyWhitelistboolfalseEscape hatch for a non-loopback bind with an empty allowedIps. Without it, that combination refuses to start — any reachable host could otherwise drive iptables.
logLeveldebug/info/warn/errorinfoLog verbosity (journald via systemd).
versionstring1.0.0Reported in health meta.version. Managed by the installer — don't hand-edit.
geoipDbPathstringPath to a MaxMind GeoLite2 Country/City .mmdb. When set and the file exists, the node reports GeoIP available and geo_filter rules become usable. The DB is licensed and not shipped — download it yourself per MaxMind's terms.

Example:

json
{
  "panelUrl": "https://panel.example.com",
  "listenAddress": "127.0.0.1",
  "listenPort": 8472,
  "allowedIps": ["10.0.0.5/32"],
  "trustProxy": false,
  "logLevel": "info",
  "geoipDbPath": "/etc/firewall-plus/GeoLite2-Country.mmdb"
}

The bearer token is not in this file — it lives at /etc/firewall-plus/token (64 hex chars, chmod 600; path overridable with FWP_TOKEN).

TLS

The daemon is intentionally HTTP-only. If you need encryption between panel and node, terminate TLS at a reverse proxy on the node and set trustProxy: true. Do not point the panel at https:// port 8472 directly — that's the "OpenSSL wrong version number" failure.


Node Environment Variables

Set in /etc/systemd/system/firewall-plus.service (Environment= lines), then systemctl daemon-reload && systemctl restart firewall-plus.

VariableDefaultDescription
FWP_CONFIG/etc/firewall-plus/config.jsonConfig file path.
FWP_TOKEN/etc/firewall-plus/tokenBearer token file path. Must contain exactly 64 hex characters.
FWP_STATE_DIR/var/lib/firewall-plusState directory (server configs, snapshots, queue state).
FWP_LOG_LEVELfrom configOverrides logLevel.
FWP_SKIP_IPTABLESunsetDev mode: when 1, skips all snapshot/restore/iptables work — config is still written to disk and the queue flows normally. Used by the test scripts.
FWP_IPTABLES_BINauto-detectForce the iptables binary, e.g. /usr/sbin/iptables-nft. The daemon auto-prefers the nft-backed binaries when present.
FWP_IPTABLES_SAVE_BINauto-detectForce the save binary, e.g. /usr/sbin/iptables-nft-save.
FWP_IPTABLES_RESTORE_BINauto-detectForce the restore binary, e.g. /usr/sbin/iptables-nft-restore.
FWP_IPTABLES_RESTORE_TIMEOUT_MS120000Max wait for a single iptables-restore, clamped to 10s–600s. Raise only to ride out netfilter contention (e.g. Docker on the same host) — it doesn't remove the contention.
FWP_IPSET_BINauto-detectForce the ipset binary.
FWP_CHAIN_REbuilt-inOverride the regex used to recognize Firewall-Plus chains (FWP-*). Drift checker and inspector. Almost never needed.
FWP_CONNTRACK_PATHauto-detectPath to conntrack data for SMART metrics. Only touch on exotic kernels.
FWP_METRICS_TICK_MSbuilt-inMetrics collection tick interval. Lower = finer charts, more CPU.
FWP_TEST_TOKENTest scripts only: token used by load-test-apply.mjs / test-queue.mjs.

Panel Admin Settings

Admin → Firewall → Settings. Stored in firewall_admin_settings; changes take effect immediately.

Limits

SettingDescription
max_rules_per_serverMaximum firewall rules a single server may have. Enforced by the LimitChecker on create.
max_whitelist_entriesMaximum whitelist entries per server.
max_blacklist_entriesMaximum blacklist entries per server.
max_abusedb_saved_lookupsMaximum saved AbuseIPDB lookups retained per server.

Nodes

SettingDescription
node_ping_interval_secondsHow often the panel health-checks each node.
node_offline_fail_thresholdFailed health checks before a node is marked OFFLINE (default 2). When a node returns ONLINE, a reconcile is dispatched automatically.
node_offline_webhook_maxMaximum offline notifications sent per node incident — prevents webhook spam during flapping.

Notifications & AbuseIPDB

SettingDescription
webhook_urlAdmin Discord webhook for firewall events (applies, node incidents, SMART attacks). See Webhooks & Alerts.
abusedb_enabledMaster switch for the AbuseIPDB client tab and API.
audit_retention_daysDays of audit history kept; pruned daily by firewall-plus:prune-audit-logs (default 90).
tos_textTerms-of-Service text users must accept before any firewall mutation. Supports markdown.
log_levelPanel-side firewall log verbosity.

SMART detection

SettingDescription
smart_alphaEWMA smoothing factor (0–1). Higher reacts faster, noisier.
smart_anomaly_multiplierHow many multiples over the EWMA baseline counts as an anomaly. Lower = more sensitive.
smart_warmup_samplesSamples collected before detection arms — avoids false positives on fresh servers.
smart_rate_limitRate cap applied by SMART mitigations.
smart_owner_email_enabledWhen on, server owners receive email alerts for SMART attack events (panel mailable), in addition to their per-server Discord webhook. Off = Discord-only.

Global toggles

The settings page also carries the global enable switch (master off switch for the whole addon) and the fleet access toggle; the Emergency page holds emergency_mode (blocks all user mutations) and per-rule-type fleet disables. See the runbook-style procedures on the CLI page.

Common mistakes

  • Changing listenPort/listenAddress on the node without updating the node's FQDN/port in Admin → Firewall → Nodes — health checks start failing silently.
  • Setting trustProxy: true without an actual proxy — the IP whitelist becomes spoofable.
  • Copying the Wings daemon URL scheme (HTTPS) onto the Firewall-Plus node FQDN — the daemon speaks plain HTTP.