Skip to content

Caddy Warden: Caddyfile Reference ​

Comprehensive syntax and configuration options for Caddy Warden (github.com/routewarden/caddy-warden).


1. Directive Ordering ​

Caddy evaluates HTTP handler directives strictly according to an internal order. Custom third-party directives like routewarden (or route_warden) do not have a hardcoded position in Caddy's directive list. If placed alongside handlers like reverse_proxy without ordering, Caddy fails at startup with:

text
directive 'routewarden' is not an ordered HTTP handler, so it cannot be used here - try placing within a route block or using the order global option

To resolve this, declare directive ordering in your Caddyfile's global options block:

{    order routewarden before basicauth}

TIP

Using a route Block: Alternatively, you can encapsulate RouteWarden and your upstream proxy inside a route { ... } block, which tells Caddy to execute directives strictly in the order they are written:

caddy
example.com {
    route {
        routewarden {
            # configuration
        }
        reverse_proxy backend:8080
    }
}

2. Complete Caddyfile Schema ​

routewarden {    # Boolean Flags    enabled <true|false>                        # Default: true    debug <true|false>                          # Default: false (verbose diagnostic logs)    security_log <true|false>                   # Default: true (emit structured JSON audit events on stdout)    enable_default_patterns <true|false>        # Default: true (.env, .git, backups, keys, etc.)    enable_default_allow_patterns <true|false>  # Default: true (/robots.txt, /favicon.ico, etc.)    check_query <true|false>                    # Default: false (inspect URI query strings)    check_headers <headers...>                  # Optional: inspect forwarded headers (e.g. X-Forwarded-Uri X-Rewrite-URL)    # Path Patterns to Block or Challenge (Go RE2 Regular Expressions)    block_patterns <regex...>    # Safe Whitelist Patterns (Overrides blocking)    allow_patterns <regex...>    # IP / CIDR Subnet Allowlist (Bypasses all checks)    allowed_ips <ip_or_cidr...>    # HTTP Methods to Inspect (Default: GET)    methods <methods...>    # Response Actions    response {        mode <json|html|text|xml|redirect|captcha|silent_drop|gzip_bomb|tarpit|fake_success|ratelimit|proxy|infinite_stream>        status_code <int>        body <string>        redirect_url <url>        proxy_url <url>        gzip_bomb_mb <int>        retry_after_seconds <int>        tarpit_delay_ms <int>        stream_size_mb <int>        captcha {            provider <turnstile|hcaptcha|recaptcha>            site_key <key>        }    }}

3. Configuration Properties ​

DirectiveTypeDefaultDescription
enabledbooltrueEnables or disables RouteWarden inspection.
debugboolfalseEnables verbose diagnostic logging in Caddy's logger.
security_logbooltrueEmits single-line structured JSON security events on stdout for CrowdSec, SIEMs, or log aggregators on blocked requests.
enable_default_patternsbooltrueBlocks high-risk files (.env, .git, .aws, .ssh, .sql, .bak, etc.).
enable_default_allow_patternsbooltrueWhitelists standard files like /robots.txt, /favicon.ico, /sitemap.xml.
check_queryboolfalseWhen enabled, also evaluates query parameters for sensitive file targets.
block_patternslist[]Additional regex patterns to intercept.
allow_patternslist[]Regex patterns that should always be allowed through.
allowed_ipslist[]IPv4, IPv6, or CIDR blocks exempted from checks.
methodslist["GET"]HTTP verbs to inspect (e.g. methods GET POST). Non-matching verbs bypass inspection.

IMPORTANT

Inspecting Non-GET Methods (methods): By default, RouteWarden only inspects GET requests (methods GET). If you are blocking API endpoints, authentication routes (e.g. POST /api/auth/login), or administrative actions that accept POST, PUT, DELETE, or PATCH, you must configure methods to include them (e.g. methods GET POST PUT DELETE PATCH HEAD). Unlisted HTTP verbs bypass RouteWarden entirely and flow straight to the backend.

TIP

CrowdSec Integration: For automated attacker remediation using security_log, see the CrowdSec Integration Guide.


4. Response Modes Matrix ​

ModeOptionsTypical Use Case
jsonstatus_code, bodyREST API protection with clean JSON error
htmlstatus_code, bodyCustom branded 404 or 403 error page
textstatus_code, bodyMinimal plain-text rejection
redirectstatus_code, redirect_urlDeflect scanners to honeypot or warning page
captchacaptcha.provider, captcha.site_keyChallenge suspicious visits via Cloudflare Turnstile/hCaptcha
silent_dropNoneReset TCP connection immediately (conn.Close())
gzip_bombstatus_code, gzip_bomb_mbActive defense memory-exhaustion trap
tarpittarpit_delay_msSlowloris defense trickling bytes to tie up scanner concurrency
ratelimitstatus_code, retry_after_seconds429 Too Many Requests response
proxyproxy_urlTransparent canary/forensics honeypot mirror
fake_successstatus_code, bodySynthetic decoy responses (wp-login, fake .env)

WARNING

silent_drop Behind Edge Proxies / CDNs (502 Bad Gateway): In silent_drop mode, RouteWarden terminates the TCP socket immediately without sending an HTTP status line. If Caddy is deployed behind Cloudflare, AWS ALB, NGINX, Traefik, or any reverse proxy / CDN, the edge proxy detects an abrupt connection termination and presents a 502 Bad Gateway error to the client.

When debugging unexpected 502 errors or when clean client responses are required, switch to mode json or mode html with status_code 403 or 404.


5. JSON Configuration (Caddy REST API) ​

For zero-downtime environments configured via Caddy's dynamic API:

{  "handler": "routewarden",  "enabled": true,  "enable_default_patterns": true,  "allowed_ips": ["10.0.0.0/8", "192.168.1.50"],  "methods": ["GET", "POST"],  "block_patterns": ["(?i)^/admin(/.*)?$"],  "allow_patterns": ["(?i)^/admin/health$"],  "response": {    "mode": "json",    "status_code": 403,    "body": "{\"error\":\"Forbidden: Authorized Access Only\"}"  }}

Released under the MIT License.