Traefik
Kubernetes
Client Certificate Authentication
Networking
Cloud Services

How to enable Client Certificate Authentication with Traefik Kubernetes?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Enabling client certificate authentication in Traefik means configuring mutual TLS, where the server presents its certificate and the client must present one too. In Kubernetes, the main tasks are storing the client CA in a secret, defining a Traefik TLS option that requires client verification, and attaching that option to the route that should be protected. Once that is in place, Traefik rejects unauthenticated clients during the TLS handshake before your application ever sees the request.

Understand The Two Certificate Roles

A common source of confusion is that two different trust relationships exist at the same time.

The first is the normal server-side TLS certificate that Traefik presents to browsers or API clients. That usually comes from a standard Kubernetes TLS secret.

The second is the certificate authority that Traefik trusts for incoming client certificates. This is the CA that signed the client certificates, and it must be configured separately.

If you mix those two roles together, the handshake will not behave the way you expect.

Create A Secret For The Client CA

Traefik needs access to the CA certificate that issued client certificates. A simple way to provide it is with a Kubernetes secret.

bash
kubectl create secret generic mtls-client-ca \
  --from-file=tls.ca=ca.crt \
  -n apps

That secret contains the trusted client CA. It is not the same secret as the server certificate used for the public endpoint.

Require Client Certificates With TLSOption

In Traefik's Kubernetes CRD model, client certificate verification is typically configured through TLSOption.

yaml
1apiVersion: traefik.io/v1alpha1
2kind: TLSOption
3metadata:
4  name: require-client-cert
5  namespace: apps
6spec:
7  clientAuth:
8    secretNames:
9      - mtls-client-ca
10    clientAuthType: RequireAndVerifyClientCert

RequireAndVerifyClientCert is the strict mode. The client must present a certificate, and that certificate must chain to one of the trusted CAs in the referenced secret list.

If your goal is true client certificate authentication, this is the mode you usually want.

Attach The TLS Option To The Route

Defining the TLSOption is not enough by itself. You still need to bind it to the route that should enforce mutual TLS.

yaml
1apiVersion: traefik.io/v1alpha1
2kind: IngressRoute
3metadata:
4  name: whoami
5  namespace: apps
6spec:
7  entryPoints:
8    - websecure
9  routes:
10    - match: Host(`whoami.example.com`)
11      kind: Rule
12      services:
13        - name: whoami
14          port: 80
15  tls:
16    secretName: whoami-server-tls
17    options:
18      name: require-client-cert
19      namespace: apps

Now the route requires both a valid server certificate and a client certificate signed by the trusted CA.

Test The Handshake End To End

The fastest realistic test is curl with the client certificate and private key.

bash
1curl https://whoami.example.com \
2  --cert client.crt \
3  --key client.key \
4  --cacert server-ca.crt

If the certificates are valid and the route is wired correctly, the request succeeds. If you omit the client certificate, the handshake should fail before the request reaches the backend service.

This test validates the whole chain: DNS, server TLS, client authentication, and upstream routing.

Namespace Placement And Authorization

Traefik CRDs and secrets are namespaced resources, so namespace placement matters. If the TLSOption references the wrong secret or the wrong namespace, the configuration may look correct but still fail at runtime.

Also remember that mTLS answers an authentication question, not an authorization question. A verified client certificate proves the client belongs to a trusted CA, but it does not automatically tell your application what that client is allowed to do. If the backend needs subject or issuer information for authorization, plan how that identity will be forwarded or mapped.

Common Pitfalls

The most common mistake is reusing the server TLS secret as the trusted client CA secret. Those two inputs serve different purposes.

Another issue is defining the TLSOption correctly but never attaching it to the actual IngressRoute. In that case, Traefik will continue accepting ordinary TLS traffic.

Namespace mismatches are also frequent in Kubernetes deployments. Keep the route, the TLSOption, and the CA secret placement explicit.

Finally, do not test only in a browser. Browser certificate prompts can make failures harder to interpret. A direct curl command is usually clearer during setup.

Summary

  • Traefik client certificate authentication is mutual TLS.
  • Store the trusted client CA in a Kubernetes secret separate from the server certificate.
  • Use a TLSOption with RequireAndVerifyClientCert to enforce verification.
  • Attach that option to the protected Traefik route.
  • Test with a real client certificate and keep authentication separate from authorization.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.