mtls with traefik, step-ca, and http-01 challenge

look ma, no vpn!

# introduction

This is a shortened, amnesia-proof checklist to set up mTLS with Traefik. The core ideas have been covered in some random person’s blog1 (of course).

# software requirements

# traefik configuration

Traefik at the very least needs a file provider configured, i.e.

# /etc/traefik/traefik.yml
providers:
  file:
    directory: "/etc/traefik/dynamic"
    watch: true

This is enabled so that we can provide an alternative TLS options without overriding the defaults. This save time on repeating the same configuration block on all our routers.

# /etc/traefik/dynamic/mtls.yml
tls:
  options:
    mtls:
      clientAuth:
        caFiles:
          - /path/to/root_ca.crt
        clientAuthType: RequireAndVerifyClientCert

The last configuration value effectively enables mTLS (server requiring clients to provide valid certificates).

Now, on the default entrypoint, set the above TLS options as the default options for the entrypoint:

entrypoints:
  websecure:
    http:
      tls:
        options: "mtls@file"
        certResolver: local

And last but not least, set up the local cert resolver.

certificatesResolvers:
  local:
    acme:
      caserver: https://example.org/acme/acme/directory
      storage: /etc/traefik/certs/acme.json
      httpChallenge:
        entryPoint: web

Replace https://example.org/acme/acme/directory with the endpoint to the CA’s acme path.

# networking requirements

Server A should be able to resolve https://example.org/acme/acme/directory to server B’s CA endpoint.

The HTTP-01 challenge also requires that server B be able to reach server A’s Traefik router hosts. This means server B will receive a request from Traefik running on server A requesting a cert for some router a.example.org. Server B will need to be able to reach a.example.org:80/.well-known/acme-challenge/* in order to complete the challenge.