Deploy, configure, secure, and maintain Traefik v3 with full coverage of static configuration, Docker provider labels, HTTP/TCP/UDP routing, all 25+ built-in middlewares, TLS/ACME (Let's Encrypt), API/dashboard, observability, v2-to-v3 migration, and production deployment patterns. Ships 10 reference files: - static-configuration.md — complete YAML schema with all keys and defaults - docker-provider.md — full Docker label reference with examples - http-routing.md — all rule matchers, priority, syntax - middleware-catalog.md — every middleware with YAML config - tls-acme.md — ACME resolvers, challenges, TLS options, custom certs - tcp-routing.md — TCP/UDP routing, SNI matching, TLS passthrough - api-dashboard.md — all API endpoints, dashboard security - observability.md — Prometheus/OTel metrics, access logs, tracing, ping - migration-v2-to-v3.md — breaking changes and migration steps - production-deployment.md — Docker Compose, security hardening, HA Source: https://doc.traefik.io/traefik/ Signed-off-by: Jasper <magnus@groktop.us>
15 KiB
Middleware Catalog
Middleware modifies requests before they reach services or modifies responses before they reach clients. Middleware attaches to routers (applied to matching requests) or services (applied to requests handled by that service). Router middlewares execute before service middlewares.
Path Modifiers
AddPrefix
Adds a path prefix before forwarding to the backend.
http:
middlewares:
api-prefix:
addPrefix:
prefix: "/api/v2"
Example: Request to /users becomes /api/v2/users to the backend.
StripPrefix
Removes matching path prefixes before forwarding.
http:
middlewares:
strip-api:
stripPrefix:
prefixes:
- "/api"
- "/v1"
forceSlash: false # If true, ensures trailing slash after stripping
Example: /api/users → /users, /v1/products → /products
StripPrefixRegex
Removes path portions matching a regex.
http:
middlewares:
strip-version:
stripPrefixRegex:
regex:
- "/[a-z]+/[0-9]+"
ReplacePath
Replaces the entire path with a fixed value.
http:
middlewares:
replace:
replacePath:
path: "/fallback"
ReplacePathRegex
Replaces path portions using regex capture groups.
http:
middlewares:
rewrite-api:
replacePathRegex:
regex: "^/api/v1/(.*)"
replacement: "/v2/$1"
Redirects
RedirectScheme
Redirects requests based on the scheme.
http:
middlewares:
https-redirect:
redirectScheme:
scheme: https
port: "443"
permanent: true
RedirectRegex
Redirects using regex matching and replacement on the entire URL.
http:
middlewares:
domain-redirect:
redirectRegex:
regex: "^http://old-domain.com/(.*)"
replacement: "https://new-domain.com/$1"
permanent: true
Security & Authentication
BasicAuth
HTTP Basic Authentication with bcrypt passwords.
http:
middlewares:
auth:
basicAuth:
users:
- "admin:$2y$05$..." # bcrypt hash
- "user:$apr1$..." # Apache MD5
usersFile: "/etc/traefik/auth/.htpasswd" # Alternative to inline users
realm: "Traefik" # Realm sent in WWW-Authenticate header
headerField: "X-WebAuth-User" # Inject authenticated user into this header
removeHeader: true # Remove Authorization header before backend
Generate password hashes:
# bcrypt (recommended)
htpasswd -nbB admin "password" | sed -e 's/\$/\$\$/g'
# Or use the usersFile with htpasswd
htpasswd -nbB admin "password" >> /etc/traefik/auth/.htpasswd
DigestAuth
HTTP Digest Authentication.
http:
middlewares:
digest-auth:
digestAuth:
users:
- "user:realm:hash"
usersFile: "/etc/traefik/auth/.htdigest"
realm: "Traefik"
removeHeader: true
headerField: "X-WebAuth-User"
ForwardAuth
Delegates authentication to an external service.
http:
middlewares:
ext-auth:
forwardAuth:
address: "http://auth-service:8080/verify" # REQUIRED
trustForwardHeader: true # Trust X-Forwarded-* headers
tls:
ca: "/etc/traefik/certs/ca.pem"
cert: "/etc/traefik/certs/cert.pem"
key: "/etc/traefik/certs/key.pem"
insecureSkipVerify: false
tls.caOptional: false # Client cert not required
authResponseHeaders:
X-Auth-User: "X-Auth-User" # Map response headers to request headers
X-Auth-Token: "X-Auth-Token"
authResponseHeadersRegex: "^X-Auth-" # Regex matching response headers to forward
authRequestHeaders:
X-My-Header: "X-Forwarded-Proto" # Map request headers to forward auth
authSetHeaders:
X-Forwarded-User: "{!header.X-Auth-User!}" # Set headers from auth response
addAuthCookiesToResponse:
- "session_token" # Remove auth cookies from backend response
maxClientConnectDuration: 30s # Max time for auth request
maxBodySize: 0 # Max body size to forward (0=unlimited)
IPAllowList
Restricts allowed client IPs.
http:
middlewares:
ip-whitelist:
ipAllowList:
sourceRange:
- "10.0.0.0/8"
- "192.168.0.0/16"
- "203.0.113.0/24"
ipStrategy:
depth: 1 # X-Forwarded-For depth to check
excludedIPs: [] # IPs to exclude from X-Forwarded-For chain
InFlightReq
Limits simultaneous connections.
http:
middlewares:
concurrency-limit:
inFlightReq:
amount: 100 # Max simultaneous requests
sourceCriterion:
requestHost: true # Track by host
requestRemoteAddr: true # Track by remote address
ipStrategy:
depth: 1
excludedIPs: []
RateLimit
Limits request frequency (per-source-IP by default).
http:
middlewares:
ratelimit:
rateLimit:
average: 100 # Average requests per second (REQUIRED)
burst: 200 # Burst size (default: average)
period: 1s # Evaluation period (default: 1s)
sourceCriterion:
requestHost: true
requestRemoteAddr: true
ipStrategy:
depth: 1
excludedIPs: []
# For Redis-backed distributed rate limiting:
# Requires Traefik Enterprise or Hub
Distributed RateLimit
Redis-backed rate limiting (requires Traefik Enterprise or Hub).
# Distributed rate limiting is a Traefik Hub/Enterprise feature
# Not available in Traefik Proxy OSS
http:
middlewares:
dist-ratelimit:
distributedRateLimit:
average: 100
burst: 200
period: 1s
sourceCriterion:
requestRemoteAddr: true
Headers
Modifies request and response headers, and sets security-related headers.
http:
middlewares:
sec-headers:
headers:
# --- Custom Header Modifications ---
customRequestHeaders: # Add/override request headers
X-Scope: "internal"
X-Forwarded-Proto: "https"
customResponseHeaders: # Add/override response headers
X-Custom: "value"
# --- CORS Headers ---
accessControlAllowCredentials: true
accessControlAllowMethods:
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "OPTIONS"
accessControlAllowOriginList:
- "https://app.example.com"
- "https://admin.example.com"
accessControlAllowOriginListRegex:
- "^https://[a-z]+\\.example\\.com$"
accessControlExposeHeaders:
- "X-Custom-Header"
accessControlMaxAge: 100
accessControlAllowHeaders:
- "Content-Type"
- "Authorization"
addVaryHeader: true
# --- Security Headers ---
# These set the corresponding HTTP security headers
hostsProxyHeaders:
- "X-Forwarded-Host"
sslRedirect: true # Redirect HTTP to HTTPS
sslTemporaryRedirect: true # Use 302 instead of 301 for SSL redirect
sslHost: "app.example.com" # Host in the Location header for SSL redirect
sslProxyHeaders:
X-Forwarded-Proto: "https"
sslForceHost: true # Force SSL Host header
stsSeconds: 315360000 # HSTS max-age (seconds)
stsIncludeSubdomains: true # HSTS includeSubDomains
stsPreload: true # HSTS preload
forceSTSHeader: true # Force STS header even for non-TLS
frameDeny: true # X-Frame-Options: DENY
customFrameOptionsValue: "" # Custom X-Frame-Options value (overrides frameDeny)
contentTypeNosniff: true # X-Content-Type-Options: nosniff
browserXssFilter: true # X-XSS-Protection: 1; mode=block
customBrowserXSSValue: "" # Custom X-XSS-Protection value
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
contentSecurityPolicyReportOnly: ""
publicKey: "" # HPKP public key (deprecated, avoid)
referrerPolicy: "strict-origin-when-cross-origin"
permissionsPolicy: "camera=(), microphone=(), geolocation=()" # Feature-Policy equivalent
isDevelopment: false # Disables Host header checking for dev
# --- Request/Response Modification ---
allowedHosts:
- "example.com"
- "api.example.com" # Reject if Host not in this list
customBrowserXSSValue: ""
sslProxyHeaders:
X-Forwarded-Proto: "https" # Trust this header for SSL detection
Request Lifecycle
Retry
Retries requests on connection failures.
http:
middlewares:
retry:
retry:
attempts: 3 # Number of retry attempts (REQUIRED)
initialInterval: 100ms # Initial backoff interval
- Retries only on network errors, not HTTP status codes
- Requests with body are NOT retried (safety measure for non-idempotent POSTs)
CircuitBreaker
Prevents requests to unhealthy services.
http:
middlewares:
cb:
circuitBreaker:
expression: "NetworkErrorRatio() > 0.5" # REQURIED
checkPeriod: 100ms
fallbackDuration: 300s # Time in half-open state before full recovery
recoveryDuration: 10s # Time before attempting recovery
Available expressions:
NetworkErrorRatio()— ratio of network errors (connection refused, timeout, DNS failure)ResponseCodeRatio(min, max, divisorMin, divisorMax)— ratio of status codes in rangeLatencyAtQuantileMS(quantile)— latency at given quantile (e.g., 50.0 for median)Count40x() / Count50x() / CountGateway()— HTTP status code counters- Combine with
&&,||, comparison operators
Examples:
expression: "NetworkErrorRatio() > 0.5" # 50%+ network errors
expression: "ResponseCodeRatio(500, 599, 0, 600) > 0.2" # 20%+ 5xx
expression: "LatencyAtQuantileMS(50.0) > 5000" # Median latency > 5s
expression: "NetworkErrorRatio() > 0.1 || ResponseCodeRatio(500, 599, 0, 600) > 0.2"
Buffering
Buffers request/response bodies before forwarding.
http:
middlewares:
buf:
buffering:
maxRequestBodyBytes: 10485760 # 10MB max request body in memory
memRequestBodyBytes: 2097152 # 2MB in-memory limit before spilling to disk
maxResponseBodyBytes: 10485760 # 10MB max response body in memory
memResponseBodyBytes: 2097152 # 2MB in-memory limit before spilling to disk
retryExpression: "IsNetworkError() && Attempts() < 3" # Retry conditions
Errors
Defines custom error pages for specific status codes.
http:
middlewares:
err-pages:
errors:
status:
- "500-599"
- "400-404"
service: "error-service@file" # Service that serves error pages
query: "/error-pages/{status}.html" # Query to the error service
How it works: When a backend returns a status matching the range, the client's request is re-routed to the error service. The error service receives a modified request with the path specified in query.
Compress
Compresses responses using gzip.
http:
middlewares:
gzip:
compress:
excludedContentTypes: # Don't compress these
- "text/event-stream"
- "image/png"
- "image/jpeg"
minResponseBodyBytes: 1024 # Minimum size to compress
defaultEncoding: "gzip" # or "deflate", "zstd" (v3)
ContentType
Prevents Traefik from auto-detecting Content-Type from response body.
http:
middlewares:
no-sniff:
contentType: {}
- Just setting this middleware prevents Go's
http.DetectContentType()from running - Forces backend to set explicit Content-Type
Authentication & Protocol
PassTLSClientCert
Passes the TLS client certificate to the backend via headers.
http:
middlewares:
pass-cert:
passTLSClientCert:
pem: true # Pass PEM-encoded cert
info:
notAfter: true # Include expiry date
notBefore: true # Include issue date
sans: true # Include Subject Alternative Names
subject:
commonName: true
country: true
domainComponent: true
locality: true
organization: true
organizationalUnit: true
province: true
serialNumber: true
issuer:
commonName: true
country: true
domainComponent: true
locality: true
organization: true
organizationalUnit: true
province: true
serialNumber: true
GrpcWeb
Converts gRPC-web requests to gRPC (HTTP/2) for backends.
http:
middlewares:
grpcweb:
grpcWeb:
allowOrigins:
- "*"
EncodedCharacters
Controls handling of encoded characters in request paths.
http:
middlewares:
encode-check:
encodedCharacters:
allowEncodedSlash: false
allowEncodedBackSlash: false
allowEncodedNullCharacter: false
allowEncodedSemicolon: false
allowEncodedPercent: false
allowEncodedQuestionMark: false
allowEncodedHash: false
Combining Middleware
Chain
Groups multiple middlewares into a reusable chain.
http:
middlewares:
standard-chain:
chain:
middlewares:
- "ratelimit"
- "auth"
- "sec-headers"
# Reference the chain as a single middleware
http:
routers:
app:
rule: "Host(`app.example.com`)"
middlewares:
- "standard-chain"
- "custom-middleware" # Chain + additional middleware
Middleware Execution Order
When multiple middlewares are attached to a router, they execute in the order listed. Common ordering patterns:
- Rate limiting — apply limits early before expensive processing
- IP allowlist — block IPs before any processing
- Authentication — verify identity before processing
- Headers — modify headers after identity is established
- AddPrefix / StripPrefix — adjust path before routing
- Redirect — redirect before backend processing
- Compress — compress the response on the way back
- Errors — final error page handling
- Retry / CircuitBreaker — at the service level
Middleware Scope
Middlewares declared via Docker labels are scoped to that Docker provider. They are NOT accessible from other providers unless qualified with the provider namespace.
# Reference a middleware from the "file" provider in a Docker router
labels:
- "traefik.http.routers.app.middlewares=my-mw@file"
# Reference a middleware from the current provider (Docker)
labels:
- "traefik.http.routers.app.middlewares=my-mw"
When using the File provider, middlewares defined in that file are accessible by name without namespace. To reference Docker-defined middlewares from a File provider router, use the @docker suffix.