Inbound mTLS
Require client certificates on HTTPS using named trust profiles
What it is
Inbound mTLS makes the proxy verify client certificates on HTTPS. You define trust profiles (which CAs may issue those clients), then either require a profile for all HTTPS on the entrypoint or only for specific routes (selected by TLS SNI).
Server certificates are still configured separately via autocert. Inbound mTLS only controls client trust.
Trust profiles
At the root of your config:
inbound_mtls_profiles:
corp:
use_system_cas: false # optional: include OS trust store
ca_files:
- /path/to/ca-chain.pem # PEM CA certs; at least one of use_system_cas or ca_filesEach profile must have at least one of use_system_cas or ca_files. Paths must be readable and contain valid PEM CAs.
Entrypoint-wide (all HTTPS)
entrypoint:
inbound_mtls_profile: corpEvery HTTPS listener on that entrypoint then requires a client cert that chains to the corp pool.
You cannot set inbound_mtls_profile on individual routes when this is set.
Per-route (no entrypoint profile)
Omit entrypoint.inbound_mtls_profile. On HTTP-based routes (http, https, h2c, fileserver), set inbound_mtls_profile to a name from inbound_mtls_profiles.
For those routes, the TLS handshake requires a client cert when SNI matches that route. Hostnames without a profile stay optional client certs. The HTTP Host and TLS SNI must resolve to the same route for secured routes; otherwise the server responds with 421 Misdirected Request.
See Configuring Routes for how route files and Docker labels are structured.
Route file
# config.yml
inbound_mtls_profiles:
corp:
ca_files:
- /path/to/client-ca.pem
providers:
include:
- config/api.yml# config/api.yml
api.example.com:
host: 10.0.9.98
port: 80
inbound_mtls_profile: corpDocker Compose
services:
api:
image: myapp
labels:
proxy.aliases: api.example.com
proxy.#1.port: 80
proxy.#1.inbound_mtls_profile: corpPractical notes
- Wrong or missing client cert: TLS handshake fails (no HTTP response).
use_system_cas: truealone can trust very broad issuers; for internal mTLS, prefer a dedicatedca_fileschain.- Go’s TLS stack does not check CRL/OCSP for client certs here.
- After changing CA files, reload or restart so pools are rebuilt.