Configuration

One YAML schema, with env-var overrides.

DFENS is configured from a single YAML file, layered over built-in defaults, with any value overridable from the environment. The image ships a minimal working config so an out-of-the-box container runs with sensible defaults.

How configuration loads

Three layers are merged, later winning over earlier:

  1. Built-in defaults. Every key has one, so a config file may set only what it changes.
  2. YAML file. Passed with serve --config <path>. The image's entrypoint points this at /etc/ai-firewall/config.yaml.
  3. Environment variables. Override any key (see below).
Note

Unknown or misspelled YAML keys are silently ignored rather than rejected. Double-check key names against this page when a setting seems to have no effect.

A representative config.yaml:

config.yaml
server:
  listen: ":8080"
  state_dir: "/data"            # must be writable — see deployment

rules:
  dir: "/etc/ai-firewall/rules.d"
  registry_path: "/etc/ai-firewall/registry.yaml"

engine:
  block_response: error         # or "soft"

audit:
  sink: stdout                  # stdout | file | both

auth:
  mode: passthrough             # or "vault"

providers:
  openai:
    enabled: true
  anthropic:
    enabled: true

metrics:
  enabled: true
  listen: ":9090"               # MUST differ from server.listen

admin:
  token_env: "AI_FIREWALL_ADMIN_TOKEN"
  healthz_path: "/health"

Environment-variable overrides

Any key maps to an environment variable: prefix AI_FIREWALL_, and a double underscore (__) for each level of nesting. The double underscore is needed because key names themselves contain single underscores.

Config keyEnvironment variable
server.listenAI_FIREWALL_SERVER__LISTEN
server.max_request_body_bytesAI_FIREWALL_SERVER__MAX_REQUEST_BODY_BYTES
auth.modeAI_FIREWALL_AUTH__MODE
providers.openai.upstreamAI_FIREWALL_PROVIDERS__OPENAI__UPSTREAM
admin.healthz_pathAI_FIREWALL_ADMIN__HEALTHZ_PATH
Common trap

AI_FIREWALL_ADMIN_TOKEN (single underscore) is not a config override. It is the value whose variable name is what admin.token_env points at. To override the token's variable name you'd set AI_FIREWALL_ADMIN__TOKEN_ENV (double underscore). Keep the two straight: token_env names the variable; the named variable holds the secret.

server

KeyDefaultPurpose
listen:8080Proxy + inspect listen address.
read_timeout30sRequest read timeout.
write_timeout600sResponse write timeout (long, for streaming).
idle_timeout120sKeep-alive idle timeout.
max_request_body_bytes10485761 MiB cap; larger bodies get 413.
state_dir/var/lib/ai-firewallWritable dir for the audit sequence counter, ruleset cache, and disable overlay.
state_dir

state_dir must be writable by the process. In containers with a read-only root filesystem, set it to a mounted writable path (the deployment examples use /data). If it is empty or unwritable, the audit sequencer generates a new host identity each start instead of persisting one.

auth (upstream)

auth.mode controls how DFENS authenticates to the upstream provider. This is separate from inbound client authentication below.

Client authentication (inbound)

DFENS can require callers to authenticate to the proxy before any request reaches a provider route or /v1/inspect. It's controlled by admin.client_token_env, the name of an environment variable holding the token:

enable client auth
admin:
  client_token_env: "AI_FIREWALL_CLIENT_TOKEN"   # names the env var…

# …and the value lives in the environment, out of the config file
export AI_FIREWALL_CLIENT_TOKEN=$(openssl rand -hex 32)

Callers then present the token in a dedicated header:

authenticated request
curl -X POST http://dfens.internal:8080/v1/inspect \
  -H "X-AI-Firewall-Key: $AI_FIREWALL_CLIENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"hi"}'
Health stays open

/health and the /admin/* control plane are not affected by client auth: health is always unauthenticated, and admin has its own separate token.

providers

Each provider block controls whether its adapter is active and where clean traffic is forwarded. Enabling a provider requires an absolute scheme://host upstream.

Providerenabledupstream default
openaitruehttps://api.openai.com
anthropictruehttps://api.anthropic.com
geminitruehttps://generativelanguage.googleapis.com
azurefalse— (set your resource endpoint)
bedrockfalse— (set endpoint + region)

Per-provider upstream_timeout defaults to 60s for the enabled three.

rules & engine

KeyDefaultPurpose
rules.dir/etc/ai-firewall/rules.dDirectory of .conf rule files.
rules.registry_path/etc/ai-firewall/registry.yamlRule-ID registry.
engine.block_responseerrorerror (403) or soft (200 synthetic turn).
engine.block_messageAssistant text returned in soft mode.
engine.dos_actionblockWhat to do when the per-request evaluation budget is exceeded.

The image bakes in the default rule set and registry. To run your own rules, mount a directory over rules.dir (see Deployment).

audit

Every block decision emits a structured JSONL audit event naming the firing rule, its severity, phase, and matched snippet.

stdout is the right default in containers: your existing log pipeline (Fluent Bit, Vector, Loki, Cloud Logging) is the durable record.

metrics

DFENS exposes Prometheus metrics on a separate listener so the metrics surface is never served on the same port as proxy traffic.

KeyDefault
metrics.enabledtrue
metrics.listen:9090
metrics.path/metrics
Validation

metrics.listen must differ from server.listen. The process refuses to start otherwise. This keeps the metrics endpoint off the proxy port by construction.

admin

The control-plane endpoints (/admin/*: disable/enable a rule at runtime, list state) are token-authenticated and off by default.

KeyDefaultPurpose
admin.token_envAI_FIREWALL_ADMIN_TOKENName of the env var holding the admin bearer token.
admin.client_token_envAI_FIREWALL_CLIENT_TOKENEnv var for the inbound client token (data-plane auth).
admin.client_auth_rate_limit_per_minute60Per-IP limit on failed client-auth attempts.
admin.healthz_path/healthHealth endpoint path.
admin.rate_limit_per_minute30Per-IP rate limit on admin calls.
Dark by default

If the token variable is unset, every /admin/* route returns 404 rather than 401: an unconfigured admin surface is invisible, not just closed. Set the token only where you need runtime rule control, and treat it as a high-value secret.

Next: Deployment. Docker, Compose, and Kubernetes.