-
-
Notifications
You must be signed in to change notification settings - Fork 5
Configuration Reference
Fabrizio Salmi edited this page Sep 6, 2026
·
1 revision
| Directive | Meaning | Example |
|---|---|---|
error_codes |
Space-separated HTTP status codes to count | error_codes 404 500 401 |
max_error_count |
Errors from one IP before a ban | max_error_count 10 |
ban_duration |
Initial ban length, human readable |
ban_duration 5s, 10m, 1h
|
| Directive | Default | Meaning |
|---|---|---|
ban_duration_multiplier |
1.0 |
Multiplies the ban length on each repeat offence. 1.5 grows it, 1 keeps it flat |
error_count_timeout |
disabled | Sliding window. If the gap between two errors exceeds this, the count restarts at 1. See How banning works |
whitelist |
empty | IPs and CIDRs that are never banned. whitelist 127.0.0.1 ::1 192.168.1.0/24
|
cidr_bans |
empty | CIDR ranges banned outright. cidr_bans 10.0.0.0/8 172.16.0.0/12
|
ban_status_code |
403 |
Status returned to a banned client. Only 403 or 429 are accepted |
ban_response_body |
empty | Response body for banned clients. Without it the body is empty |
custom_response_header |
none | Comma-separated values added to the response, each under the key X-Custom-MIB-Info
|
log_request_headers |
none | Request headers to include in the log line when an IP is banned. log_request_headers User-Agent X-Forwarded-For
|
log_level |
Caddy's global level |
debug, info, warn or error for this middleware only |
per_path <path> overrides the global settings for one path, and accepts the same options: error_codes, max_error_count, ban_duration, ban_duration_multiplier and error_count_timeout.
caddy_mib {
error_codes 404 500 401
max_error_count 10
ban_duration 5s
per_path /login {
error_codes 404
max_error_count 5
ban_duration 10s
ban_duration_multiplier 2
error_count_timeout 15m
}
per_path /api {
error_codes 404 500
max_error_count 8
ban_duration 15s
}
}Two things to keep in mind:
-
Path bans and the global ban are counted separately. An IP can exhaust the
/loginbudget and be banned there while still under the global limit elsewhere. -
error_count_timeoutis inherited from the global block when a per-path block does not set it. The other options are not inherited in a way you should rely on: set explicitly what matters for that path.
{
admin off
log {
level debug
output stdout
format console
}
}
:8080 {
route {
caddy_mib {
error_codes 404 500 401
max_error_count 10
ban_duration 5s
ban_duration_multiplier 1.5
error_count_timeout 1h
whitelist 127.0.0.1 ::1 192.168.1.0/24
cidr_bans 10.0.0.0/8
ban_status_code 429
ban_response_body "You have been temporarily blocked due to excessive errors."
log_request_headers User-Agent X-Forwarded-For
log_level debug
per_path /login {
error_codes 404
max_error_count 5
ban_duration 10s
ban_duration_multiplier 2
error_count_timeout 15m
}
}
handle {
respond "Hello world!" 404
}
}
}Caddy MIB · README · Releases · Report a bug · AGPL-3.0