traefik/traefik
TLS
Traefik handles TLS at three layers: certificate management for serving traffic, ACME for issuing certificates automatically, and OCSP stapling for online revocation.
Code map
| File | Purpose |
|---|---|
pkg/tls/tls.go |
Configuration types: Options, CipherSuites, CurveIDs, ClientAuth. |
pkg/tls/tlsmanager.go |
Runtime TLS manager. Owns the certificate store and the tls.Config factories. |
pkg/tls/certificate.go |
Domain certificate matching and SNI selection. |
pkg/tls/certificate_store.go |
Cached certificate index keyed by domain / wildcard / SAN. |
pkg/tls/cipher.go |
Cipher and curve allow-lists, including Go-version-aware filtering. |
pkg/tls/ocsp.go |
OCSP stapling. |
pkg/tls/version.go |
Constants for VersionTLS1.0–1.3. |
pkg/tls/generate/ |
Self-signed certificate helpers used in tests. |
pkg/provider/acme/ |
ACME provider: account, challenges, renewal, storage. |
pkg/provider/tailscale/ |
Tailscale-issued certificates resolver. |
Static vs dynamic TLS
Like most things in Traefik, TLS is split:
- Static —
tls.options(named cipher / version / mTLS templates),tls.stores(default certificate file, default cert chain),certificatesResolvers(ACME accounts, CA URLs, key types). - Dynamic —
tls.certificates(per-host certificate files),tls.optionsreferenced by routers,tls.storesoverrides.
Dynamic TLS material is delivered just like any other dynamic configuration: a provider emits a dynamic.Configuration containing TLS.Certificates, TLS.Options, and TLS.Stores, and the watcher hands it to the TLS manager.
TLS manager
pkg/tls/tlsmanager.go owns:
- A
certsmap keyed by store name →*CertificateStore. - A
configsmap oftls.optionsname → compiled*tls.Config. - A reference to the ACME challenge in progress (so TLS-ALPN-01 can be served on the live listener).
Its public API is small:
func (m *Manager) Get(storeName, optionsName string) (*tls.Config, error)
func (m *Manager) UpdateConfigs(...)
func (m *Manager) GetStore(name string) *CertificateStoreGet is called by entry points to obtain a *tls.Config per connection. The returned config has a GetCertificate callback that consults the certificate store to pick a certificate based on the SNI name (or the default certificate if SNI is missing).
Certificate store
pkg/tls/certificate_store.go is the lookup table. It indexes certificates by:
- Exact match on a hostname.
- Wildcard match (
*.example.com). - SANs declared in the certificate.
When multiple certificates can serve the same name, the most-specific match wins (exact > wildcard).
Cipher and version filtering
pkg/tls/cipher.go maps the names accepted in tls.options.cipherSuites (e.g. TLS_AES_256_GCM_SHA384) to the Go constants. It transparently filters out cipher suites that are no longer supported by the running Go version, so configurations don't have to be tuned per Go release.
tls.options.minVersion and maxVersion accept VersionTLS10 … VersionTLS13. The defaults are MinVersion=TLS12 and the latest supported MaxVersion.
Mutual TLS
tls.options.clientAuth controls mTLS. The supported modes are the standard Go ones: NoClientCert, RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, RequireAndVerifyClientCert. The CA pool is loaded from the configured trust files.
The pkg/middlewares/passtlsclientcert middleware reads the negotiated client certificate and forwards selected fields as headers to the upstream — typical for mTLS-protected services that still want to know who's calling.
ACME provider
pkg/provider/acme/provider.go (40k bytes) implements ACME (RFC 8555) using github.com/go-acme/lego/v4. Its responsibilities:
- Track which domains need certificates (derived from active routers and
tls.domainsconfig). - Acquire and renew certificates via HTTP-01, TLS-ALPN-01, or DNS-01 challenges.
- Persist account and certificate state on disk (
pkg/provider/acme/local_store.go). - Expose certificates back into the dynamic configuration so the TLS manager picks them up.
graph TD
Conf[Static config<br/>certificatesResolvers] --> Provider[ACME Provider]
Routers[Active routers] -->|requested domains| Provider
Provider -->|HTTP-01| Endpoint["acme-http@internal\n(challenge_http.go)"]
Provider -->|TLS-ALPN-01| TLSManager[tlsmanager<br/>via challenge_tls.go]
Provider -->|DNS-01| Lego[Lego DNS plugins]
Provider --> Store[local_store.go on disk]
Provider -->|dynamic.Message| Watcher[Configuration watcher]
Watcher --> TLSManagerThe challenge code is split:
pkg/provider/acme/challenge_http.go— HTTP-01 handler exposed at theacme-http@internalroute.pkg/provider/acme/challenge_tls.go— TLS-ALPN-01 by stuffing a temporary certificate into the TLS manager.- DNS-01 challenges delegate to one of dozens of DNS providers shipped by Lego (selected by the resolver's
dnsChallenge.providersetting).
Local storage
pkg/provider/acme/local_store.go reads and writes a JSON file containing:
- The ACME account.
- The list of issued certificates, keyed by domain, with their PEM material and resolver name.
The file is written atomically (rename-after-write) and locked with platform-specific helpers (local_store_unix.go, local_store_windows.go).
OCSP stapling
pkg/tls/ocsp.go implements optional OCSP stapling. When enabled in static config (OCSPConfig), it:
- Parses each certificate's OCSP responder URL (
OCSPextension). - Periodically fetches the OCSP response.
- Attaches the response to the
*tls.Certificateso it is sent during the handshake.
Failure to fetch is degraded to a warning — the certificate is still served but without a stapled response.
Tailscale resolver
pkg/provider/tailscale/ is a non-ACME certificate resolver. It calls Tailscale's local API to issue certificates for nodes in the tailnet. Because the Tailscale daemon is the issuer, no challenge handling is required — the certificate just appears.
It is wired in pkg/config/static/static_config.go as another CertificateResolver type.
SPIFFE / workload identity
cmd/traefik/traefik.go initializes a SPIFFE workload-API client (github.com/spiffe/go-spiffe/v2) when Spiffe is configured. The client provides X.509-SVIDs that can be used as upstream client certificates and to verify server certificates by SPIFFE ID. The integration is at the transport layer, not in the TLS manager — see pkg/server/service/transport.go.
Tests
pkg/tls/tlsmanager_test.go— store assembly, SNI matching, default cert.pkg/tls/certificate_store_test.go— wildcard / SAN matching.pkg/tls/ocsp_test.go— OCSP stapling lifecycle.pkg/provider/acme/provider_test.go— domain extraction, renewal logic.integration/https_test.go— end-to-end TLS scenarios.integration/acme_test.go— full ACME issuance against pebble (a Let's Encrypt staging server).
Entry points for modification
- New TLS option: add to
pkg/config/dynamic/tls.go(underpkg/config/dynamic) and consume inpkg/tls/tlsmanager.go. - New ACME challenge type: extend
pkg/provider/acme/provider.go. DNS challenges are managed by Lego — adding a DNS provider usually only means upgrading thelegodependency. - New certificate resolver type (e.g. another non-ACME source): mirror the Tailscale provider's structure.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.