Configuration¶
Website Defender is configured at runtime via the config/config.yaml file. This page documents all available configuration options.
Full Configuration Reference¶
Below is the complete configuration file with all available options and their default values:
# Database configuration
# Supported drivers: sqlite (default), postgres, mysql
database:
driver: sqlite
# SQLite settings (used when driver is sqlite)
# file-path: ./data/app.db
# PostgreSQL settings (used when driver is postgres)
# host: localhost
# port: 5432
# name: open_website_defender
# user: postgres
# password: your_password
# ssl-mode: disable
# MySQL settings (used when driver is mysql)
# host: localhost
# port: 3306
# name: open_website_defender
# user: root
# password: your_password
# Security configuration
security:
# JWT secret key for token signing.
# If empty, a random key is generated on each restart.
# IMPORTANT: Set this in production to persist tokens across restarts.
jwt-secret: ""
# Token expiration time in hours (default: 24)
token-expiration-hours: 24
# Number of days a trusted device is remembered (default: 7)
trusted-device-days: 7
# CORS configuration
cors:
# Allowed origins. Empty list = reflect any origin (permissive, for dev only).
# In production, set explicit origins:
# allowed-origins:
# - "https://example.com"
# - "https://admin.example.com"
allowed-origins: []
allow-credentials: true
# Security response headers
headers:
# Enable HSTS (only enable if behind HTTPS)
hsts-enabled: false
# X-Frame-Options: DENY, SAMEORIGIN, or empty to disable
frame-options: "DENY"
# Rate limiting configuration
rate-limit:
enabled: true
# Global rate limit: max requests per minute per IP
requests-per-minute: 100
# Login-specific rate limit (stricter)
login:
requests-per-minute: 5
# Lockout duration in seconds after exceeding login rate limit
lockout-duration: 300
# Request filtering configuration (WAF: SQLi, XSS, Path Traversal detection)
request-filtering:
enabled: true
# Semantic analysis engine (deeper SQLi/XSS detection)
semantic-analysis:
enabled: true
# Geo-IP blocking configuration
geo-blocking:
enabled: false
# Path to MaxMind GeoLite2-Country.mmdb file
# Download from: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
database-path: ""
# Blocked countries are managed via the admin API (POST /geo-block-rules)
# Cache configuration
cache:
# Maximum in-memory cache size in MB (default: 100)
# size-mb: 100
# Multi-instance sync polling interval in seconds (0 = disabled)
# sync-interval: 0
# Server configuration
server:
# Listening port (default: 9999, can also be set via PORT env var)
# port: 9999
# Maximum request body size in MB (default: 10)
max-body-size-mb: 10
# Default user credentials (created on first startup)
default-user:
username: defender
password: defender
# OAuth2/OIDC Provider configuration
oauth:
enabled: true
issuer: "https://auth.example.com/wall"
rsa-private-key-path: ""
authorization-code-lifetime: 300
access-token-lifetime: 3600
refresh-token-lifetime: 2592000
id-token-lifetime: 3600
# Threat detection (auto-ban on anomalous behavior)
threat-detection:
enabled: true
status-code-threshold: 20
status-code-window: 60
rate-limit-abuse-threshold: 5
rate-limit-abuse-window: 300
auto-ban-duration: 3600
scan-threshold: 10
scan-window: 300
scan-ban-duration: 14400
brute-force-threshold: 10
brute-force-window: 600
brute-force-ban-duration: 3600
# JS Challenge (Proof-of-Work)
js-challenge:
enabled: false
mode: "suspicious" # off | suspicious | all
difficulty: 4 # 1-6
cookie-ttl: 86400
cookie-secret: ""
# Webhook notifications
webhook:
url: ""
timeout: 5
events:
- auto_ban
- brute_force
- scan_detected
# Wall (frontend runtime) configuration
# These values are injected into the frontend HTML at runtime.
# wall:
# backend-host: "" # API base URL for cross-origin setups
# guard-domain: "" # Cookie domain for SSO across subdomains
# Bot management configuration
bot-management:
enabled: false
# Escalate from JS challenge to CAPTCHA on repeat offenders
challenge-escalation: false
# CAPTCHA provider configuration
captcha:
# Provider: hcaptcha or turnstile
provider: ""
site-key: ""
secret-key: ""
cookie-ttl: 86400
# Trusted proxy IPs (for correct client IP detection behind reverse proxies)
trustedProxies:
- "127.0.0.1"
- "::1"
Configuration Sections¶
Database¶
Configures the database backend. Website Defender supports SQLite, PostgreSQL, and MySQL.
For detailed database configuration with examples for each driver, see Database.
Cache¶
| Setting | Default | Description |
|---|---|---|
size-mb |
100 |
Maximum in-memory cache size in megabytes |
sync-interval |
0 (disabled) |
Multi-instance sync polling interval in seconds |
Security¶
| Setting | Default | Description |
|---|---|---|
jwt-secret |
"" (random) |
Secret key for JWT token signing |
token-expiration-hours |
24 |
JWT token validity period in hours |
trusted-device-days |
7 |
Number of days a trusted device is remembered |
admin-recovery-key |
"" (disabled) |
Recovery key for resetting admin 2FA |
admin-recovery-local-only |
true |
Restrict 2FA recovery to localhost |
cors.allowed-origins |
[] (permissive) |
List of allowed CORS origins |
cors.allow-credentials |
true |
Allow credentials in CORS requests |
headers.hsts-enabled |
false |
Enable HTTP Strict Transport Security |
headers.frame-options |
"DENY" |
X-Frame-Options header value |
Production Security Settings
In production, always set:
- A stable
jwt-secretto persist tokens across restarts - Explicit
cors.allowed-originsinstead of the permissive default hsts-enabled: trueif serving over HTTPS
Rate Limiting¶
| Setting | Default | Description |
|---|---|---|
enabled |
true |
Enable or disable rate limiting |
requests-per-minute |
100 |
Global per-IP request limit |
login.requests-per-minute |
5 |
Login endpoint per-IP limit |
login.lockout-duration |
300 |
Login lockout duration in seconds |
For more details, see Rate Limiting.
Request Filtering (WAF)¶
| Setting | Default | Description |
|---|---|---|
enabled |
true |
Enable or disable the WAF |
semantic-analysis.enabled |
true |
Enable semantic analysis engine for deeper SQLi/XSS detection |
For more details, see WAF Rules.
Geo-Blocking¶
| Setting | Default | Description |
|---|---|---|
enabled |
false |
Enable or disable geo-IP blocking |
database-path |
"" |
Path to MaxMind GeoLite2-Country .mmdb file |
For more details, see Geo-IP Blocking.
Server¶
| Setting | Default | Description |
|---|---|---|
port |
9999 |
Listening port (can also be set via PORT env var) |
max-body-size-mb |
10 |
Maximum request body size in megabytes |
Default User¶
| Setting | Default | Description |
|---|---|---|
username |
defender |
Default admin username created on first startup |
password |
defender |
Default admin password created on first startup |
Change Default Credentials
Change the default username and password immediately after first login.
Threat Detection¶
| Setting | Default | Description |
|---|---|---|
enabled |
true |
Enable or disable automatic threat detection |
status-code-threshold |
20 |
4xx responses before auto-ban |
status-code-window |
60 |
Time window for 4xx counting (seconds) |
rate-limit-abuse-threshold |
5 |
Rate limit hits before auto-ban |
rate-limit-abuse-window |
300 |
Time window for rate limit counting (seconds) |
auto-ban-duration |
3600 |
Default auto-ban duration (seconds) |
scan-threshold |
10 |
404 responses before scan detection |
scan-window |
300 |
Time window for scan counting (seconds) |
scan-ban-duration |
14400 |
Scan detection ban duration (seconds) |
brute-force-threshold |
10 |
Failed logins before brute force detection |
brute-force-window |
600 |
Time window for brute force counting (seconds) |
brute-force-ban-duration |
3600 |
Brute force ban duration (seconds) |
For more details, see Threat Detection.
JS Challenge¶
| Setting | Default | Description |
|---|---|---|
enabled |
false |
Enable or disable JS Challenge |
mode |
"suspicious" |
Challenge mode: off, suspicious, or all |
difficulty |
4 |
Number of leading zeros required (1-6) |
cookie-ttl |
86400 |
Pass cookie lifetime in seconds |
cookie-secret |
"" |
HMAC secret for cookie signing |
For more details, see JS Challenge.
Webhook¶
| Setting | Default | Description |
|---|---|---|
url |
"" (disabled) |
Webhook endpoint URL |
timeout |
5 |
Request timeout in seconds |
events |
[auto_ban, brute_force, scan_detected] |
Event types that trigger notifications |
For more details, see Webhook.
Wall (Frontend Runtime)¶
| Setting | Default | Description |
|---|---|---|
backend-host |
"" (same-origin) |
API base URL, only needed for cross-origin deployments |
guard-domain |
"" |
Cookie domain for SSO across subdomains |
These values are injected into the frontend HTML at runtime via window.__APP_CONFIG__. In most deployments you do not need to set them -- they are only required when the frontend and backend are served from different origins, or when you need guard cookies to be shared across subdomains.
Bot Management¶
| Setting | Default | Description |
|---|---|---|
enabled |
false |
Enable or disable bot management |
challenge-escalation |
false |
Escalate from JS challenge to CAPTCHA on repeat offenders |
captcha.provider |
"" (disabled) |
CAPTCHA provider: hcaptcha or turnstile |
captcha.site-key |
"" |
CAPTCHA provider site key |
captcha.secret-key |
"" |
CAPTCHA provider secret key |
captcha.cookie-ttl |
86400 |
CAPTCHA pass cookie lifetime in seconds |
Trusted Proxies¶
The trustedProxies list specifies which proxy IPs are trusted for forwarding headers like X-Forwarded-For. This ensures correct client IP detection when running behind a reverse proxy.
Environment Variables¶
Build-time environment variables are documented separately. See Environment Variables.