Separate TLS settings for different entrypoints not working

Hello there :waving_hand:t5:

I’m currently working on configuring Traefik to handle two distinct TLS profiles on separate entrypoints, but I’m running into an issue where only one profile is applied correctly (regular HTTPS) the other is completely ignored, despite being specified in the configuration. I tried specifying the TLS options both on entrypoint and router level, but the issue persists.

My goal is:

  • Serve regular HTTPS on port 443 using a certificate/key pair issued by a public CA (e.g., Comodo).

  • Serve mutual TLS on port 8443, requiring and validating client certificates issued by a local self-signed CA.

I’m using Docker Compose and have configured two main files:

docker-compose.yml
---
networks:
  default:
    driver: bridge
    ipam:
      config:
        - subnet: ${SUBNET}

x-service-defaults: &service-defaults
  security_opt:
    - no-new-privileges:true
  deploy:
    restart_policy:
      condition: on-failure
      delay: 5s
      max_attempts: 5
      window: 120s

services:
  traefik:
    <<: *service-defaults
    image: docker.io/library/traefik:${TRAEFIK_DOCKER_TAG}
    command:
      - --accesslog.format=text
      - --accesslog=true
      - --api.basepath=/traefik
      - --api.dashboard=true
      - --api.insecure=false
      - --entrypoints.mtls.address=:8443
      - --entrypoints.mtls.http.tls.options=mtls@file
      - --entrypoints.web-secure.address=:443
      - --entrypoints.web-secure.http.tls.options=https@file
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.permanent=true
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.web.http.redirections.entrypoint.to=web-secure
      - --log.level=DEBUG
      - --ping=true
      - --providers.docker.exposedbydefault=false
      - --providers.file.filename=/mnt/config/tls.toml
    healthcheck:
      test: ["CMD", "traefik", "healthcheck", "--ping"]
      start_period: 10s
      interval: 5s
      timeout: 1s
      retries: 5
    networks:
      default:
        aliases:
          - ${PUBLIC_FQDN}
    ports:
      - 80:80/tcp
      - 8080:8080/tcp
      - 443:443/tcp
      - 8443:8443/tcp
    volumes:
      - ./config/traefik:/mnt/config:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      traefik.enable: true
      traefik.http.middlewares.ipallowlist.ipallowlist.sourcerange: ${SUBNET}
      traefik.http.routers.internal-dashboard.middlewares: ipallowlist
      traefik.http.routers.internal-dashboard.entrypoints: web-secure
      traefik.http.routers.internal-dashboard.rule: PathPrefix(`/traefik`)
      traefik.http.routers.internal-dashboard.service: api@internal

  grafana:
    <<: *service-defaults
    image: docker.io/grafana/grafana:${GRAFANA_DOCKER_TAG}
    environment:
      - PUBLIC_FQDN
      - GF_SERVER_ROOT_URL=/grafana
      - GF_SERVER_SERVE_FROM_SUB_PATH=true
      - GF_USERS_ALLOW_SIGN_UP=false
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/api/health"]
      start_period: 10s
      interval: 5s
      timeout: 1s
      retries: 5
    volumes:
      - ./data/grafana:/var/lib/grafana
      - ./config/grafana/provisioning:/etc/grafana/provisioning
    labels:
      traefik.enable: true
      traefik.http.routers.grafana.entrypoints: web-secure
      traefik.http.routers.grafana.rule: PathPrefix(`/grafana`)
      # traefik.http.routers.grafana.tls.options: https@file
      traefik.http.services.grafana.loadbalancer.server.port: 3000

  prometheus:
    <<: *service-defaults
    image: docker.io/prom/prometheus:${PROMETHEUS_DOCKER_TAG}
    command:
      - --config.file=/etc/prometheus/config.yml
      - --storage.tsdb.path=/usr/local/share/prometheus
      - --web.external-url=https://${PUBLIC_FQDN}/prometheus
      - --web.route-prefix=/prometheus/
    environment:
      - PUBLIC_FQDN
    healthcheck:
      test:
        [
          "CMD",
          "wget",
          "--spider",
          "http://localhost:9090/prometheus/-/healthy",
        ]
      start_period: 10s
      interval: 5s
      timeout: 1s
      retries: 5
    volumes:
      - ./config/prometheus:/etc/prometheus
      - ./data/prometheus:/usr/local/share/prometheus
    labels:
      traefik.enable: true
      traefik.http.routers.prometheus.entrypoints: mtls
      traefik.http.routers.prometheus.rule: PathPrefix(`/prometheus`)
      # traefik.http.routers.prometheus.tls.options: mtls@file
      traefik.http.services.prometheus.loadbalancer.server.port: 9090
tls.toml
[[tls.certificates]]
certFile = "/mnt/config/comodo.crt"
keyFile = "/mnt/config/comodo.key"

[tls.options]
[tls.options.https]
sniStrict = true
minVersion = "VersionTLS12"

[tls.options.mtls]
sniStrict = true
minVersion = "VersionTLS12"

[tls.options.mtls.clientAuth]
caFiles = ["/mnt/config/my-ca.crt"]
clientAuthType = "RequireAndVerifyClientCert"

Has anyone successfully implemented a similar setup? If so, could you please review what I might be missing or doing wrong?

Thank you very much in advance!