Traefik sits at the edge of a cluster or Docker host and routes every inbound request, so its API, its certificate store and its connection to the container engine are some of the most valuable things on the platform. Securing Traefik is mostly about a handful of customer-side settings: how the API and dashboard are exposed, which TLS options and certificate resolvers apply, which middlewares sit in front of each router, and how Traefik reads configuration from Docker or Kubernetes. This guide walks through each of those with the exact option names from the Traefik documentation, a hardening baseline and the logging you need to detect misuse. It is written for platform, DevOps and security engineers running Traefik Proxy as an ingress controller or reverse proxy. For general TLS settings that apply to any edge proxy, see the TLS Configuration Baseline Guide.
This is an independent guide from NHI Mgmt Group, based on Traefik Labs' public documentation as of November 2026. It is not sponsored or reviewed by Traefik Labs. Product features change, so confirm settings against Traefik Labs' current documentation.
Key takeaways
- Route the dashboard, never publish it raw. Keep
api.insecureat its default offalseand expose the API through a router toapi@internalwith authentication and an IP allow list in front. - The Docker provider is a privileged identity. Whatever can talk to the Docker API can control the host, so give Traefik a filtered, authenticated path to the engine rather than a bare socket mount.
- Set
exposedByDefaulttofalse. Then only containers labelledtraefik.enable=trueget routes, and nothing reaches the internet by accident. - Define the
defaultTLS option. Routers without their own TLS options use it, so a minimum version and cipher list set there covers every router at once. - Trust forwarded headers only from known proxies. Use
forwardedHeaders.trustedIPsandproxyProtocol.trustedIPson entrypoints; theinsecurevariants are for testing.
How identity and access work in Traefik
Traefik Proxy does not keep its own user directory. Identity enters in three places, and each is controlled by configuration you own:
- Who can reach the API and dashboard: the API is off unless you set
api(defaultfalse); turning it on also turns onapi.dashboard. Access is then decided by the router you attach to theapi@internalservice and the middlewares on it. - Who can reach applications behind Traefik: authentication is done by middlewares (
basicAuth,digestAuth,forwardAuth) and network restriction byipAllowList. Mutual TLS is a TLS option (clientAuth). - What Traefik itself can reach: providers such as Docker and Kubernetes give Traefik credentials to read the container engine or cluster API. These are machine identities, and they usually carry more power than any human login on the proxy.
The API exposes a lot. Traefik's documentation lists GET endpoints including /api/rawdata (dynamic configuration, errors and status), /api/support-dump (an archive of anonymised static and runtime configuration) and, when api.debug is true, the Go /debug/vars and /debug/pprof/* endpoints. The docs state that running the API and dashboard in production is not recommended because they expose all configuration, including sensitive data, and that if you do run them they should at least sit behind authentication and authorisation, with the API port kept off public networks.
| Option | Default | Recommended production value |
|---|---|---|
api | false | Leave off unless operators need the dashboard; enable on internal instances only |
api.insecure | false | false: expose through a router to api@internal instead |
api.debug | false | false; enable briefly for a support case, then turn off |
api.basePath | / | Optional path prefix; it cannot be combined with api.insecure |
| Dashboard path | /dashboard/ | Router rule must match both /api and /dashboard |
Admin roles and privileged access
Administrative power over Traefik is held by whoever can change its configuration, not by a role inside the product. Map those paths and treat each as privileged access.
Static configuration
The static file, CLI flags or environment variables decide entrypoints, providers, the API and certificate resolvers. Anyone who can edit them, or the Helm values that render them, can switch on api.insecure or point a provider elsewhere. Keep static configuration in version control with mandatory review, and restrict write access to the Traefik deployment.
Dynamic configuration
Routers, services and middlewares arrive from providers. With the Docker provider, anyone who can start a container with traefik.* labels can create a route. With Kubernetes, anyone who can create IngressRoute or Middleware objects can do the same in the namespaces Traefik watches. Two controls narrow this:
providers.docker.exposedByDefault: false: the default istrue; withfalse, containers withouttraefik.enable=trueare ignored.providers.docker.constraints: a label expression usingLabel()orLabelRegex()that limits which containers Traefik will route. An empty value includes every detected container. Thetraefik.*namespace is reserved and cannot be a custom constraint key.
In Kubernetes, scope who can create Traefik custom resources through RBAC. See the Kubernetes RBAC Guide.
Securing the dashboard router
- Create a dedicated entrypoint on an internal address or interface for administration.
- Create a router with a
Host()rule for an internal name, matching/apiand/dashboard, with serviceapi@internal. - Attach
ipAllowListwith the administrators' network ranges, then an authentication middleware.forwardAuthto your identity provider gives single sign-on and MFA;basicAuthis a fallback. - Attach TLS with a certificate from your resolver and the
defaultTLS option. - Test from outside the allowed range (expect
403, theipAllowListdefaultrejectStatusCode) and without credentials (expect a challenge).
Rollback is simple: remove the router and the dashboard is unreachable while routing continues. Since the API is read-only GET, the main risk of exposure is disclosure of configuration and backend topology, which then helps an attacker target services.
Integrations, API tokens and service accounts
Traefik holds several machine credentials. Each needs an owner, a storage location and a rotation plan.
| Credential or interface | Where it lives | What it can do | Control |
|---|---|---|---|
| Docker API access | providers.docker.endpoint, default unix:///var/run/docker.sock | Read, and through the socket potentially control, the Docker engine and host | TLS client certificates (tls.ca, tls.cert, tls.key), SSH, or a filtering socket proxy |
| Kubernetes service account | Traefik pod | Watch Services, Endpoints, Secrets and Traefik CRDs | Least-privilege ClusterRole, namespace scoping |
| ACME account and certificates | acme.storage, default acme.json | Private keys for every issued certificate | Restrictive file permissions, encrypted volume, backups |
| DNS provider credentials | Environment variables read by the Lego library for dnsChallenge | Change DNS records in the zone | Zone-scoped API token, secrets manager injection |
| External Account Binding | acme.eab.kid, acme.eab.hmacEncoded | Register ACME accounts with a commercial or private CA | Store as a secret, never in labels |
| basicAuth hashes | users, usersFile or a Kubernetes secret | Grant access to protected routers | BCrypt hashes, file or secret rather than labels |
The Docker provider
Traefik's documentation warns that unrestricted Docker API access is a security risk, because whoever gains control of Traefik may reach the underlying host. It lists these mitigations:
- Authenticated transport: expose the Docker daemon over TCP with TLS client certificate authentication, or over SSH with public key authentication (Docker 18.09 and later).
- Request filtering: put a socket proxy in front of the daemon that allows only the read calls Traefik needs, optionally behind HTTP basic authentication (
providers.docker.usernameandpassword). - Docker authorisation plugins: enforce policy at the daemon.
- Exposure limits: keep the socket reachable only on a private network for Traefik, on a separate container from Traefik, or confined by kernel controls such as SELinux.
Keep providers.docker.tls.insecureSkipVerify at false so Traefik verifies the daemon's certificate. Set providers.docker.network so Traefik connects to containers over a known network. See the Container Runtime Security Guide for daemon-side protection.
Certificates and ACME
Traefik obtains certificates through a certificate resolver. Choose the challenge to suit your network:
| Challenge | Option | Requirement | Security consideration |
|---|---|---|---|
| HTTP-01 | acme.httpChallenge.entryPoint | Port 80 reachable by the CA | Keep port 80 open only for the challenge and redirection |
| TLS-ALPN-01 | acme.tlsChallenge | Port 443 reachable | No extra port; works for public hosts only |
| DNS-01 | acme.dnsChallenge.provider | DNS provider API credentials | Required for wildcards; the DNS token becomes a high-value secret |
Other settings worth knowing: acme.caServer defaults to the Let's Encrypt production directory, so point it at a staging or private CA while testing; acme.keyType defaults to RSA4096; acme.certificatesDuration defaults to 2160 hours with renewal starting 30 days before expiry. The documentation states that running several Traefik instances against Let's Encrypt with the built-in resolver is unsupported, and suggests cert-manager for high availability. Our recommendation: restrict acme.json to the Traefik user (mode 600), mount it on a persistent encrypted volume, and include it in backups so a restart does not trigger mass reissuance. See the ACME and Automated Certificate Management Guide.
Logging and detection
Traefik writes two streams: the application log (log.*) and the access log (accesslog.*). Both go to standard output unless a filePath is set.
- Application log:
log.leveldefaults toERROR. UseINFOin production if you want provider and configuration events, andlog.format: jsonfor parsing. - Access log: turn on
accesslogwithformat: json. Request headers are dropped by default (accesslog.fields.headers.defaultMode: drop). If you keep headers, setAuthorizationandCookietoredactby name so credentials do not land in your SIEM. - Query strings:
accesslog.fields.queryParameters.defaultModedefaults tokeep. Set it todropwhere applications put tokens in URLs. - Metrics: Prometheus metrics use the
traefikentrypoint by default. SetmanualRouting: trueand routeprometheus@internalbehind the same protections as the dashboard, or keep the entrypoint internal. See the Prometheus Security.
| Signal | Source | Why it matters |
|---|---|---|
Requests to /api/, /dashboard/ or /debug/ from outside admin ranges | Access log | Reconnaissance of routing configuration (ATT&CK T1190 precursor) |
Bursts of 401 on basicAuth or forwardAuth routers | Access log | Password guessing against protected routers |
| New routers or middlewares appearing | Application log, /api/rawdata diff | Unreviewed container labels or CRDs creating exposure |
| Certificate obtain or renewal errors | Application log | Expiry risk or a tampered DNS credential |
| Unexpected Docker API calls from the Traefik container | Socket proxy or daemon logs | Container administration through Traefik's identity (T1609, T1552.007) |
Metrics that show the controls are working: number of internet-reachable routers with no authentication middleware (target zero for admin services); percentage of routers using the default TLS option or stricter; days to certificate expiry for the soonest certificate; count of containers routed without traefik.enable=true (target zero); time from Traefik release to production rollout.
Hardening baseline
Entrypoints
- Redirect HTTP to HTTPS:
http.redirections.entryPoint.to: websecurewithscheme: https(permanent by default). - Forwarded headers: list load balancer ranges in
forwardedHeaders.trustedIPs; keepforwardedHeaders.insecureatfalse, which the docs reserve for tests. Do the same forproxyProtocol.trustedIPs. - Timeouts and limits:
readTimeoutdefaults to60s,writeTimeoutto0s(none) andidleTimeoutto180s. Set a write timeout suited to your applications.http.maxHeaderBytesdefaults to 1 MiB. - Path handling: leave
http.sanitizePathattrue; considerhttp.encodeQuerySemicolons: truewhere backends parse semicolons differently from Traefik. - Entrypoint-wide middlewares: use
http.middlewaresto prepend a security headers middleware to every router, with fully qualified names such assecure-headers@file.
TLS options
Define the TLS option named default, which applies to any router without its own option:
minVersion: VersionTLS12(orVersionTLS13where every client supports it). The docs discourage usingmaxVersionto switch off TLS 1.3.cipherSuites: list AEAD suites only for TLS 1.2. TLS 1.3 suites are not configurable.sniStrict: true: rejects clients that do not send a matching server name, so scanners hitting the IP do not receive the default certificate.clientAuth: for service-to-service routes, setcaFilesandclientAuthType: RequireAndVerifyClientCert. See the mTLS Guide.
Without a configured certificate, Traefik generates a self-signed one; replace it in production.
Middlewares
- headers: set
stsSecondswithstsIncludeSubdomains,contentTypeNosniff: true,frameDeny: true, acontentSecurityPolicy(trial it withcontentSecurityPolicyReportOnly),referrerPolicyandpermissionsPolicy. - forwardAuth: set
authRequestHeadersexplicitly (all client headers go to the auth server when it is empty), listauthResponseHeaders, verify the auth server certificate, and setmaxBodySizeandmaxResponseBodySize, which the docs recommend to avoid memory exhaustion.trustForwardHeaderis deprecated; rely on entrypointtrustedIPs. - basicAuth: use BCrypt hashes from
htpasswd -B(MD5 and SHA1 are also accepted; our recommendation is BCrypt only), setremoveHeader: trueso credentials do not reach the backend, and in Kubernetes prefer a secret of hashed entries overkubernetes.io/basic-authsecrets, which the docs note are not hashed. - ipAllowList: without an
ipStrategythe remote address is checked. If Traefik sits behind a load balancer, setipStrategy.depthto match your exact proxy chain so a client cannot choose its own address throughX-Forwarded-For. - Rate limiting: apply
rateLimitto login and API routes. See the Rate Limiting and API Abuse Guide.
Rollout order
- Inventory routers from
/api/http/routerson an internal instance and record which have authentication and TLS. - Set
exposedByDefault: falsein staging, label the containers that should be routed, and compare the router list. - Introduce the
defaultTLS option and headers middleware in staging; test clients and use CSP report-only first. - Move the dashboard to a protected internal router and remove any
api.insecuresetting. - Replace the raw Docker socket with an authenticated or filtered endpoint; confirm routing still updates on container events.
- Promote to production one entrypoint at a time, keeping the previous static configuration ready to redeploy as rollback.
Apply Traefik security updates promptly and watch Traefik's security advisories.
Common misconfigurations
- Dashboard published with
api.insecure: trueon a public port. Fix: remove it and routeapi@internalbehindipAllowListandforwardAuth. - Every container routed automatically. With
exposedByDefaultleft attrue, a test or admin container started with a port can become reachable. Fix: setfalseand opt in by label. - Docker socket mounted straight into the Traefik container. Anyone who gains control of the Traefik process then also controls the engine. Fix: socket proxy, TLS or SSH endpoint, separate container.
forwardedHeaders.insecureleft on after testing. Clients can then set their own source address and bypass IP restrictions. Fix:trustedIPsfor your load balancers only.- Credentials in labels and logs. basicAuth hashes in labels, DNS tokens in compose files, or
Authorizationheaders kept in access logs. Fix: files or secrets, header redaction. See the Secrets Management Guide. acme.jsonlost or world-readable. Fix: persistent volume, mode600(our recommendation), backups and a staging CA for tests.
| Control area | NIST SP 800-53 Rev 5 | CIS Controls v8.1 | ISO/IEC 27001:2022 Annex A |
|---|---|---|---|
| Dashboard and API access | AC-3, AC-6, IA-2 | 6 Access Control Management | A.8.2, A.8.5 |
| Entrypoints, exposure, provider scoping | SC-7, CM-7 | 4 Secure Configuration, 12 Network Infrastructure Management | A.8.20, A.8.9 |
| TLS options and certificates | SC-8, SC-12 | 3 Data Protection | A.8.24 |
| Provider and DNS credentials | IA-5 | 5 Account Management | A.5.17 |
| Access and application logs | AU-2, AU-12 | 8 Audit Log Management | A.8.15, A.8.16 |
Practitioner checklist
- Confirm
api.insecureandapi.debugarefalseon every instance. - Expose
api@internalonly through an internal router withipAllowListand SSO throughforwardAuth. - Set
providers.docker.exposedByDefault: falseand useconstraintswhere several teams share a host. - Replace the raw Docker socket with a TLS, SSH or filtered socket proxy endpoint, and keep
insecureSkipVerifyoff. - Define the
defaultTLS option withminVersion: VersionTLS12or higher andsniStrict: true. - Redirect HTTP to HTTPS on the web entrypoint and add a headers middleware with HSTS and CSP.
- Restrict
forwardedHeaders.trustedIPsandproxyProtocol.trustedIPsto known load balancers. - Store DNS and EAB credentials in a secrets manager with zone-scoped tokens; protect and back up
acme.json. - Enable JSON access logs with header redaction and alert on admin path requests and 401 bursts.
- Track Traefik security advisories and patch within your edge-component service level.
Standards and references
- Traefik Labs: API and Dashboard
- Traefik Labs: Docker Provider
- Traefik Labs: ACME Certificate Resolver
- Traefik Labs: TLS Options
- Traefik Labs: EntryPoints
- Traefik Labs: ForwardAuth Middleware
- Traefik Labs: Logs and Access Logs
- Traefik: Security Policy and Advisories
Related NHI Mgmt Group resources: TLS Configuration Baseline Guide · API Gateway Security Guide · Web Application Firewall Guide · Kubernetes Security Guide