Security
The [security] block groups controls that apply before and around request handling: connection caps, trusted-proxy CIDRs for real-IP resolution, IP allow/deny lists (see IP filtering), rate limits (see Rate limiting), and response security headers (HSTS, CSP, custom).
TLS termination and mTLS are configured under [tls]; see TLS.
Connection limit
Section titled “Connection limit”max_connections caps concurrent client connections. Static: enforced at the acceptor.
security: max_connections: 512[security]max_connections = 512Trusted proxies
Section titled “Trusted proxies”When the proxy sits behind a load balancer or ingress, client IPs in X-Forwarded-For can be trusted for real-IP resolution. trusted_proxies is a global CIDR list: it applies to all requests and is not overridable per domain or route.
When set and the peer IP is in this list, the proxy walks X-Forwarded-For right-to-left and uses the first IP not in the trusted list as the real client IP. This real IP drives rate limiting (limit_by = "ip" or "combined") and IP filtering. The same list gates PROXY protocol headers: only trusted peers may supply a PROXY address.
When empty (default), the non-forgeable TCP peer IP is used directly. Dynamic (hot-reloadable).
security: trusted_proxies: - "10.0.0.0/8" - "172.16.0.0/12"[security]trusted_proxies = ["10.0.0.0/8", "172.16.0.0/12"]Security headers
Section titled “Security headers”HSTS, CSP, and custom headers attach to responses. The global [security.headers] block applies to all responses. Per-domain and per-route overrides use the same shape inside [domains.security.headers] and [domains.routes.security.headers] respectively: each is a whole-block replace: the most specific scope that defines a security.headers block replaces the parent’s block entirely (no field-level merge).
Example (global):
security: headers: custom: - name: "X-Frame-Options" value: "DENY" - name: "X-Content-Type-Options" value: "nosniff" hsts: enabled: true max_age: 31536000 include_subdomains: false preload: false csp: enabled: true policy: "default-src 'self'; script-src 'self' 'unsafe-inline'"[security.headers]custom = [ { name = "X-Frame-Options", value = "DENY" }, { name = "X-Content-Type-Options", value = "nosniff" },]
[security.headers.hsts]enabled = truemax_age = 31536000include_subdomains = falsepreload = false
[security.headers.csp]enabled = truepolicy = "default-src 'self'; script-src 'self' 'unsafe-inline'"Header cascade vs. security headers
Section titled “Header cascade vs. security headers”There are two header mechanisms with different semantics:
[headers](add/remove): additive cascade. Global → domain → route accumulate; for a given header name, the most specific scope wins. Nothing is replaced wholesale.security.headers: whole-block replace. Likeip_filterandrate_limit, the most specific scope that defines the block replaces the parent entirely. Settingsecurity.headerson a route silently drops any global or domainsecurity.headersfor that route.
Use [headers] for free-form request/response plumbing; use security.headers as a security policy you intend to define completely at a given scope.
Per-domain and per-route security overrides
Section titled “Per-domain and per-route security overrides”ip_filter, rate_limit, and security.headers can be overridden at the domain and route levels. Each override is a whole-block replace: it does not merge with the global config.
domains: - host: "api.example.com" security: ip_filter: mode: "allowlist" allowlist: ["10.0.0.0/8"] rate_limit: enabled: true requests_per_second: 50 burst: 100 limit_by: "ip" routes: - prefix: "/internal" backend: "backend-a:9000" security: rate_limit: enabled: false # this route is exempt[[domains]]host = "api.example.com"
[domains.security.ip_filter]mode = "allowlist"allowlist = ["10.0.0.0/8"]
[domains.security.rate_limit]enabled = truerequests_per_second = 50burst = 100limit_by = "ip"
[[domains.routes]] prefix = "/internal" backend = "backend-a:9000"
[domains.routes.security.rate_limit] enabled = false # this route is exemptForwarding headers
Section titled “Forwarding headers”The proxy sets trusted X-Forwarded-* values for backends:
X-Forwarded-For: appends the client IP (comma-separated), or creates the header.X-Forwarded-Host: set from the HTTP request authority (:authorityin HTTP/2,Hostheader in HTTP/1.1). Client-suppliedX-Forwarded-Hostvalues are not trusted and are removed first.X-Forwarded-Port/X-Forwarded-Proto: derived from the peer connection and scheme.
These do not require config. Global [headers] request add/remove lists are separate.
Related
Section titled “Related”- IP filtering:
[security.ip_filter]allowlist / denylist - Rate limiting:
[security.rate_limit]and per-domain/route overrides - TLS: certificates and mTLS
- Configuration overview