I am currently migrating from Traefik version 1 to Traefik version 3. Here's are my changes

I am currently migrating from Traefik version 1 to Traefik version 3. Here's are my changes

traefik.toml version 1 :

defaultEntryPoints = ["http", "https"]

[web]
address = ":8080"
[web.auth.basic]
users = ["admin:$apr1$kGMbPfo4$wirXXXNT9P5BqkJn1rv8J1"]

[entryPoints]
[entryPoints.http]
address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
[entryPoints.https]
address = ":443"
    [entryPoints.https.tls]
    [[entryPoints.https.tls.certificates]]
        CertFile = "/app/cert.pem"
        KeyFile = "/app/key.pem"
    [[entryPoints.https.tls.certificates]]
        CertFile = "/app/mywebsite.cert.pem"
        KeyFile = "/app/mywebsite.key.pem"

traefik.toml version 3

[entryPoints]
[entryPoints.http]
    address = ":80"
    [entryPoints.http.http.redirections.entryPoint]
    to = "https"

[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
    [[entryPoints.https.tls.certificates]]
    certFile = "/app/mywebsite.cert.pem"
    keyFile = "/app/mywebsite.key.pem"

[api]
dashboard = true
insecure = false

[log]
level = "INFO"

[accessLog]

docker-compose.yml version 1

services:
traefik:
    networks:
    - proxy
    build:
    context: ./traefik
    dockerfile: Dockerfile
    command: --docker
    restart: always
    ports:
    - "443:443"
    
    # Disable web interface access for traefik, for security purpose.
    #expose:
    #  - "8080"
    
    # Disable web interface access for traefik, for security purpose.
    #labels:
    #  - traefik.frontend.rule=Host:traefik.jstock.co
    #  - traefik.docker.network=proxy
    #  - traefik.port=8080
    
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    logging:
        driver: "json-file"
        options:
            max-file: "10"
            max-size: "10m"
            
networks:
proxy:
    external: true

docker-compose.yml version 3

services:
  traefik:
    networks:
      - proxy
    build:
      context: ./traefik2
      dockerfile: Dockerfile
    command: 
      - --api.dashboard=true
      - --api.insecure=false
      - --providers.docker=true
      - --serverstransport.insecureskipverify=true
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard port
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    logging:
      driver: "json-file"
      options:
        max-file: "10"
        max-size: "10m"

networks:
  proxy:
    external: true

However, I am getting error

traefik-1  | {"level":"error","error":"command traefik error: field not found, node: tls","time":"2025-02-28T04:36:16Z","message":"Command error"}

Do you have any idea how I can resolve such an issue? Thank you.

So you posted on Reddit and Stackoverflow, but disregard any feedback that has already been given to you.

1 Like

Here is the correct traefik.yml for such a purpose.

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https

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

tls:
  certificates:
    - certFile: "/app/xxx.me.cert.pem"
      keyFile: "/app/xxx.me.key.pem"
    - certFile: "/app/cert.pem"
      keyFile: "/app/key.pem"

providers:
  docker:
    exposedByDefault: false

log:
  level: INFO

Here's the correct labelling format for each Docker service.

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx-xxx-email.rule=Host(`email.xxx.me`)"
      - "traefik.http.routers.nginx-xxx-email.entrypoints=websecure"
      - "traefik.http.services.nginx-xxx-email.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"

tls certs are Traefik dynamic config (doc), they needs to be placed in a separate dynamic config file and loaded via providers.file (doc).

There is no tls root element in Traefik static config (doc).

Thank you. I wasn’t aware that TLS should be in a separate file.

However, I have been using this single-file configuration in production for a few weeks, and it seems to be working well. Am I missing something?

Maybe you use providers.file and read the static config file as dynamic config. That works, but isn’t best practice, kind of dirty. You never know if there will be unexpected collisions in the future.

I was puzzled for a while after reading your comment.

When I searched through my Traefik project folder, I couldn't find anything related to providers.file.

Most likely, Traefik has some forgiving backward-compatibility rule that allows my TLS configuration in the static config to work.

But you're right—I should take some time to migrate TLS to a file, so that it will continue to work in the future.

/etc/traefik/dynamic/dynamic.yaml

with content

tls:
  certificates:
    - certFile: "/app/xxx.me.cert.pem"
      keyFile: "/app/xxx.me.key.pem"

Then, in my static config file, I will use

providers:
  docker:
    exposedByDefault: false
  file:
    directory: "/etc/traefik/dynamic"  # <-- New dynamic config directory
1 Like

Note that you can watch the dynamic config directory for changes. But it will not update when the TLS cert files change, only when you "touch" the dynamic config file itself.

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