Skip to content

Configuration Keys

Every key the code reads, in one place. This page answers "what was that key called again" — press Cmd+F and search it.

For what a setting means and why you would change it, follow the link in the last column. Nothing here explains anything; that is deliberate.

The single most common mistake

FileStorage reads storage_file. FileRateLimitStorage reads file. They are different keys for the same idea, and getting it wrong does not error — the backend falls back to a hashed filename in the system temp directory, so the firewall appears to work while keeping its block list somewhere you did not choose and may lose on reboot.

Top level

Key Type What it holds
configs list Other files to merge in — paths, globs, URLs, {config_dir} / {presets_dir} tokens. Loading & Includes
global map Site-wide behaviour. Table below
storage map Where blocks are persisted. Table below
connections map Connections declared once and referred to as %connection(name)%. Named Connections
logger list Monolog handlers. Logging
events map listeners: decision listeners, each {class, args, events}. Reacting to Decisions
metrics map statsd: host, port, prefix, tags, rule_limit, or true for the defaults. Export Metrics
challenge map Challenge flow settings. Table below
tarpit map max_concurrent (default 5) and max_seconds (default 30) — see Tarpit
plugins list The rules. Table below

A configs: entry naming a file that does not exist empties the whole document

A missing include is a load failure, not a skipped line — every rule stops being configured. global.require_config: true turns that into a startup exception instead.

global:

Key Type Default
mode string block block, log, exception, disabled, lockdown Mode
panic_file string unset A file that overrides mode when it exists Panic Switch
banning_status_code int 400 Status sent when a rule blocks Status Code
banning_message string built-in Plain-text body template; {{request.id}}, {{block.status}} and {{block.rule}} are substituted Banning Message
block_page bool or map unset An HTML page instead of the message: lang, title, heading, message, styles, stylesheet, or your own template Block and lockdown pages
banning_json bool false Answer a client that prefers JSON with JSON JSON for API clients
repeat_offender_status int 0 Status for a client already on the block list Global
add_to_expire int 3600 Seconds added to a ban on each repeat hit Global
blocking_escalation list [] Window/offense/duration rules that lengthen bans Multiple Offenses
behind_proxy bool unset Assert whether a proxy sits in front Trusted Proxies
require_trusted_proxies bool false Refuse to start without trusted proxies, from either source Trusted Proxies
trusted_proxies list unset Proxies to trust during evaluation; ranges, REMOTE_ADDR, PRIVATE_SUBNETS. Ignored when the host sets its own Trusted proxies from YAML
trusted_headers list x-forwarded-for, -proto, -port Which forwarding headers to believe from them Trusted proxies from YAML
require_config bool false Refuse to start if any config input failed to load Loading
lockdown bool false Refuse everyone but lockdown_allow Lockdown
lockdown_allow list (empty) Addresses, CIDRs and start-end ranges still served. Empty serves nobody Lockdown
lockdown_status int 503 Lockdown
lockdown_retry_after int 300 Seconds in Retry-After; 0 omits it Lockdown
lockdown_message string built-in Supports {{request.id}} Lockdown
lockdown_page bool or map unset As block_page, for the lockdown response Block and lockdown pages
path_source string pathinfo pathinfo (relative to the front controller) or script_name (the file the server ran). WordPress needs script_name; front-controller apps keep the default Path Source
base_path string unset Where the application is installed, for script_name in a subdirectory Path Source
stale_source_error_after int 0 (off) Seconds before an unrefreshed source is an error Stale Rule Sources
reverse_dns map unset Who makes reverse-DNS verification's lookups: provider, providers, resolver, resolver_options, timeout_ms. Unset is PHP's own lookups Reverse DNS

storage:

Key Type
type class FileStorage, DatabaseStorage, RedisStorage, MemcachedStorage, InMemoryStorage
config map Backend-specific, below
Backend config keys
FileStorage storage_file, offense_file Paths; relative resolves against the YAML file
DatabaseStorage connection, storage_table, offenses_table, schema_check_probability Storage
RedisStorage redis, instance Requires ext-redis
MemcachedStorage memcached, instance Requires ext-memcached. Range searches are best effort
InMemoryStorage — Per-process; nothing survives the request
SharedStorage shared, local A fleet-wide list with a local copy underneath. Each is a {type, config} block — Storage

Every block-list backend also accepts record_request, which decides what a block record keeps of the visitor's cookies, headers, query and body. It defaults to an allowlist rather than everything.

Rate-limit counters are stored separately, under the RateLimit plugin's own metadata:

Backend config keys
FileRateLimitStorage file
DatabaseRateLimitStorage connection, schema_check_probability
RedisRateLimitStorage redis, instance, ttl
CacheRateLimitStorage adaptor (a pool class or a memcached:// / redis:// DSN), args, namespace, options, ttl
InMemoryRateLimitStorage —

challenge:

Key Type Default
provider string required math, altcha, turnstile, recaptcha, or a FQCN Challenges
secret string required HMAC key for pass tokens. Startup fails if empty Challenges
path string /_firewall/challenge The path a submission is recognised at, matched against getPathInfo() Add a Challenge
submit_url string path, prefixed with the request's base path Where the interstitial's form POSTs to. Only set it if a proxy rewrites paths Add a Challenge
cookie_name string fw_challenge_pass Pass-token cookie; empty disables cookie delivery. On Pantheon, start it with STYXKEY_ Challenges
header_name string X-Firewall-Challenge Header an SPA can send the token in; empty disables it Challenges
notice string or list unset Plain text shown on every challenge page, above the form A notice on the challenge page
page map unset The page's lang, title, heading, intro, button, error_message, styles and stylesheet. Startup fails on an unknown key or an unusable value Wording, language and styling
ttl int 3600 How long a pass lasts: the default for rules naming none, and the ceiling for every rule and every submission How long a pass lasts
audience string provider name aud claim, to scope tokens between instances Scoping tokens
passes_valid_from int or date unset Refuse every pass issued before this moment. One value, no storage Withdrawing a pass
revocable bool false Consult the per-nonce revocation list, at one storage read per valid pass Withdrawing a pass
provider_options map [] Per-provider settings, keyed by provider name Challenges

plugins: — one entry

Key Type Default
plugin class required The rule class
response string block allow, block, challenge, record, redirect, mark, tarpit — decides the bucket, and buckets beat weights
weight int 0 Order within its bucket; lower runs first
enable bool true
metadata map [] How the rule behaves. Below
config list [] The rule's own entries — addresses, paths, patterns

metadata: — common to every plugin

Key Type Default
name string class name What the log calls it. Name every rule Plugins
mode string enforce log observes this one rule without enforcing it Observe mode
status_code int banning_status_code Per-rule override Status Code
banning_message string banning_message Per-rule override of the block message Banning Message
block_page bool or map block_page This rule's block page, merged over the global one Block and lockdown pages
default_expiration_time int challenge.ttl on a challenge rule, else 3600 Ban length, or pass-token TTL. On a challenge rule it is capped by challenge.ttl Global
record bool true false refuses without writing to the block list. On a redirect rule the default is false and true opts in Evaluation Order
mark_as string the rule's name The signal response: mark raises, so several rules can raise one
mark_header string — Also set this header on the request when marking
redirect_to string — Required by response: redirect. Never built from the request, so it cannot become an open redirect
redirect_status int 302 301, 302, 307 or 308
default_key list [client_ip, rule_pattern] What rate limits count by, for rules declaring no key:
active map unset timezone (default UTC), days, hours, from, until — when this rule is awake Time Windows
sources list [] Pull this rule's entries from elsewhere Rule Sources
challenge_provider string challenge.provider Per-rule provider override Per-plugin providers
tarpit_seconds int — Required by response: tarpit. Capped by tarpit.max_seconds Tarpit
config list — Legacy alias for the entry's config: Legacy format

Identity-verifying plugins (User Agent, and any implementing IdentityVerificationInterface) add verify, verify_cache, verify_ttl, verify_negative_ttl, verify_suffixes, verify_claim_wait_ms, verify_slow_threshold_ms, verify_offline, verify_provider and verify_timeout_ms — see User Agent and Reverse DNS.

Every sources: option is its own table in Rule Sources, including allow_catch_all, which decides whether a source may contribute an entry matching every address, max_size / max_entries, which bound how much a refresh may bring in, and checksum / signature, which decide whether the fetched bytes are checked against what the publisher asserted.

metadata: — edge signal rules

EdgeSignal reads what a CDN decided. See Edge Signals.

Key Type Default
provider string custom cloudflare, fastly, custom
headers map [] Signal to header name; layers over the profile

Signals: bot_score, verified_bot, ja3, ja4.

config: — reputation rules

Reputation and AbuseIpdb take a map rather than a rule list. See Reputation.

Key Type Default
provider string http (abuseipdb on AbuseIpdb) abuseipdb, http, or a class implementing ReputationProviderInterface
threshold float 75 Score at or above which the rule matches, on the provider's scale
cache_ttl int provider's How long a verdict is reused
error_cache_ttl int provider's How long a failed lookup is remembered
cache_dir string temp dir Where verdicts are cached
on_error string fail_open fail_open, last_known_good
subject string client_ip What to score: client_ip, post.*, header.*, query.*, cookie.*
subject_hash string unset Send a digest of the subject instead of the value, e.g. sha256
block_status int 403 Status returned when the rule blocks
block_duration int 3600 How long the address is remembered
api_key string unset abuseipdb: required, or the rule is inert
max_age_in_days int 30 abuseipdb: how far back reports count
when list unset Conditions gating the lookup — same syntax as any rule
upstream string or map required http: the endpoint, as a source declares one. Must contain {ip}
format string json http: json, txt, csv, tsv, ndjson, yaml, xml
score_path string http: dot path to the score in the decoded body
score_pattern string http: or a regex with one capturing group, read from the raw body
trusted_path string unset http: dot path to an "allow this one" flag
trusted_pattern string unset http: or a regex for the same
content_type string application/json http: sent with an upstream.body
provider_name string see docs http: what log lines call the service
public_only bool true http: false also looks up private addresses
timeout float 2.0 Seconds to wait before giving up

PHP constants

Set before Firewall::create(). These exist because they must be readable before any YAML is parsed.

Constant Default
KANOPI_FIREWALL_CACHE_DIR system temp Where compiled config and source caches are written
KANOPI_FIREWALL_CACHE_TTL 3600 Default rule-source TTL, when a source names none
KANOPI_FIREWALL_CACHE_MAX_AGE 30 days Compiled-config entries older than this are swept; 0 disables
KANOPI_FIREWALL_CONFIG_FILE_CACHE true false (or any value FILTER_VALIDATE_BOOL reads as false, such as '0') stops the compiled config being written to files; a pool from Config::setConfigCachePool() is still used
KANOPI_FIREWALL_CACHE_MAX_STALE — How long a stale cached source may still be served
KANOPI_FIREWALL_CACHE_TIMEOUT — Fetch timeout for remote sources
KANOPI_FIREWALL_REQUIRE_CONFIG false Same as global.require_config
KANOPI_FIREWALL_SOURCES_OFFLINE false Never fetch on the request path. Also switches off reverse-DNS verification for rules that do not set verify_offline

Environment Variables covers %env(...)% substitution, which works in any value above.