Traefik is not using the default certificates provided by dynamic config

Hi there!

I recently bought a fully qualified domain name and I'm working on self-hosting a few services like Nextcloud, Immich, and others. My ISP only allows port forwarding for customers with static IPs, which I don’t want to use.

So, I thought of using Cloudflare Tunnel to access my services from anywhere, and it works great on its own. However, I wanted to challenge myself a bit and add Traefik into the mix, acting as a reverse proxy and an extra layer of control/security. I'm trying to avoid placing full trust in any single component.

That’s where things got a bit tricky.

A few days ago, I successfully generated TLS certificates using Let’s Encrypt with the dnsChallenge method. But then I started wondering—since Cloudflare Tunnel uses its own certificates, and Traefik is using Let's Encrypt certs, would that create conflicts or unexpected behavior?

To try and fix that, I generated an Origin Certificate from Cloudflare, saved them as certificate.tld.pem and key.tld.key, and mounted them into my Traefik container.

Here’s my setup/config if you want to take a look.

Here is my docker-compose.yaml file

networks:
  private:
    external: false
  public:
    external: false

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    hostname: cloudflared
    restart: unless-stopped
    command: tunnel run
    networks:
      - public
    environment:
      - TZ=${TZ}
      - TUNNEL_TOKEN=${TUNNEL_TOKEN}
  traefik:
    image: traefik:latest
    container_name: traefik
    hostname: traefik
    restart: unless-stopped
    depends_on:
      - cloudflared
    security_opt:
      - no-new-privileges:true
    networks:
      - public
      - private
    environment:
      - TZ=${TZ}
      - CF_API_EMAIL=${CF_API_EMAIL}
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./config/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./config/traefik/certificate.tld.pem:/certificate.tld.pem:ro
      - ./config/traefik/key.tld.key:/key.tld.key:ro
      - ./config/traefik/certificates.yml:/certificates.yml
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.mydomain.com`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=user:pwd"
  whoami:
    image: traefik/whoami
    container_name: whoami
    restart: unless-stopped
    depends_on:
      - traefik
    networks:
      - private
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.routers.whoami.service=whoami"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"
global:
  checkNewVersion: true
  sendAnonymousUsage: false

log:
  level: DEBUG

metrics:
  prometheus: true

api:
  dashboard: true
  debug: true
  insecure: false

entrypoints:
  websecure:
    address: ":443"
    http:
      tls: {}

serversTransport:
  insecureSkipVerify: false

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    network: "public"
    exposedByDefault: false
    watch: true
  file:
    filename: /certificates.yml
    watch: true

and here is the certificates.yml:

tls:
  domains:
    - main: "mydomain.com"
      sans:
        - "*.mydomain.com"
  stores:
    default:
      defaultCertificates:
        certFile: /certificate.tld.pem
        keyFile: /key.tld.key
  certificates:
    - certFile: /certificate.tld.pem
      keyFile: /key.tld.key

And here's the log that says traefik is using the default certificates:

traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"middlewares":{"dashboard-auth":{"basicAuth":{"users":["user:pwd"]}}},"routers":{"dashboard":{"entryPoints":["websecure"],"middlewares":["dashboard-auth@docker"],"rule":"Host(`traefik.mydomain.com`)","service":"api@internal"},"whoami":{"entryPoints":["websecure"],"rule":"Host(`whoami.mydomain.com`)","service":"whoami","tls":{}}},"services":{"traefik-homelab":{"loadBalancer":{"passHostHeader":true,"responseForwarding":{"flushInterval":"100ms"},"servers":[{"url":"http://172.19.0.2:80"}],"strategy":"wrr"}},"whoami":{"loadBalancer":{"passHostHeader":true,"responseForwarding":{"flushInterval":"100ms"},"servers":[{"url":"http://172.19.0.3:80"}],"strategy":"wrr"}}}},"tcp":{},"tls":{},"udp":{}} providerName=docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:50 > Creating middleware entryPointName=traefik middlewareName=metrics-entrypoint middlewareType=Metrics
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:50 > Creating middleware entryPointName=websecure middlewareName=metrics-entrypoint middlewareType=Metrics
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:50 > Creating middleware entryPointName=websecure middlewareName=metrics-entrypoint middlewareType=Metrics
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/auth/basic_auth.go:37 > Creating middleware entryPointName=websecure middlewareName=dashboard-auth@docker middlewareType=BasicAuth routerName=dashboard@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=websecure middlewareName=dashboard-auth@docker routerName=dashboard@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:320 > Creating load-balancer entryPointName=websecure routerName=whoami@docker serviceName=whoami@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:363 > Creating server URL=http://**.**.**.**:80 entryPointName=websecure routerName=whoami@docker serverIndex=0 serviceName=whoami@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:82 > Creating middleware entryPointName=websecure middlewareName=metrics-service middlewareType=Metrics routerName=whoami@docker serviceName=whoami@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=websecure middlewareName=metrics-service routerName=whoami@docker serviceName=whoami@docker
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:50 > Creating middleware entryPointName=websecure middlewareName=metrics-entrypoint middlewareType=Metrics
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recovery
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/metrics/metrics.go:50 > Creating middleware entryPointName=traefik middlewareName=metrics-entrypoint middlewareType=Metrics
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/server/router/tcp/manager.go:237 > Adding route for traefik.mydomain.com with TLS options default entryPointName=websecure
traefik  | 2025-07-28T14:28:48+03:00 DBG github.com/traefik/traefik/v3/pkg/server/router/tcp/manager.go:237 > Adding route for whoami.mydomain.com with TLS options default entryPointName=websecure
traefik  | 2025-07-28T14:28:55+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:228 > Serving default certificate for request: "*.mydomain.com"
traefik  | 2025-07-28T14:28:55+03:00 DBG log/log.go:245 > http: TLS handshake error from **.**.**.**:36920: remote error: tls: bad certificate

Here's the cloudflared logs:

cloudflared  | 2025-07-28T11:28:55Z ERR  error="Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared: tls: failed to verify certificate: x509: certificate is valid for **.traefik.default, not *.mydomain.com" connIndex=3 event=1 ingressRule=0 originService=https://traefik
cloudflared  | 2025-07-28T11:28:55Z ERR Request failed error="Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared: tls: failed to verify certificate: x509: certificate is valid for **.traefik.default, not *.mydomain.com" connIndex=3 dest=https://whoami.mydomain.com/ event=0 ip=****** type=http

I’ve been stuck on this issue for two weeks now and still haven’t been able to solve it. Really appreciate your help—thanks so much!

It seems you got TLS correctly enabled on your websecure entrypoint.

We use a simpler TLS config:

tls:
  options:
    default:
      minVersion: VersionTLS12
  certificates:
    - certFile: /path/to/domain.cert
      keyFile: /path/to/domain.key

Make sure the .cert file has at least two entries inside the file.

1 Like

CF Origin Certificates only provides one in .pem file.
I've tried looking up how to create the file with two entries but i've no luck i guess. But thanks for the reply. :smiley:

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.