How to renew / update user-defined (custom) certificates

I want to switch to user-defined certificates. Every 3 months I will manually renew certificates with Lego and then I want to feed them to traefik. How to do that?

Will updating certificate files in a volume with certificates suffice? Do I need to restart traefik?

P.S. this only involves update / renew already existing certificates.

Hello,

this means you are using the file provider to handle the certificates.
if your certificate definitions don't change inside the configuration, you just have to do a touch on the configuration file that contains the certificate definitions. You don't need to restart.

It does NOT work. Let me describe what I do:

I run traefik in docker swarm. I am testing if traefik will update configuration in case of changes. The changes I do is renaming the certificates files to check if traefik will switch to a default certificate. After the renaming the certificates file on localhost which is mounted via volumes (e.g. from /etc/traefik_certs/<domain>.crt --> /etc/traefik_certs/<domain>.crt.moved) and touching the dynamic config file (./config/master_dyn_cfg.yml) nothing changes. The traefik still serves the (non-default) certificates.

[more context]
In fact only docker stack rm + docker stack deploy make traefik see the changes and start serving the default certificate (since the certificate path were deliberately changed to make dynamic config wrong).

[more context]
The files are mounted correctly via volumes and I can see all the changes inside the containers (both certificates renaming and dynamic config file timestamps are updated)

traefik docker compose file:

version: "3.7"
services:
  traefik:
    command:
    - --api=true
    - --api.dashboard=true
    - --log.level=DEBUG
    - --metrics.prometheus=true
    - --metrics.prometheus.addEntryPointsLabels=true
    - --metrics.prometheus.addServicesLabels=true
    - --entryPoints.metrics.address=:8082
    - --metrics.prometheus.entryPoint=metrics
    - --entryPoints.http.address=:80
    - --entryPoints.https.address=:443
    - --entryPoints.master_postgres.address=:5432
    - --entryPoints.smtp.address=:25
    - --providers.docker.endpoint=unix:///var/run/docker.sock
    - --providers.docker.swarmMode=true
    - --providers.docker.exposedByDefault=false
    - --tracing=true
    - --tracing.jaeger=true
    - --tracing.jaeger.samplingServerURL=http://jaeger:5778/sampling
    - --tracing.jaeger.localAgentHostPort=jaeger:6831
    - --providers.docker.constraints=!LabelRegex(...)
    - --entryPoints.https.forwardedHeaders.insecure
    - --providers.file.filename=/etc/traefik/dynamic_cfg.yml
    deploy:
      replicas: 1
      labels:
        ...
      resources:
        limits:
          cpus: "3.000"
          memory: "2147483648"
        reservations:
          cpus: "1.000"
          memory: "524288000"
      placement:
        constraints:
        - node.role == manager
        - node.labels.traefik==true
    environment:
      ...
    image: traefik:v2.10.4
    init: true
    networks:
      monitored: null
      public: null
    ports:
    - mode: host
      target: 80
      published: 80
    - mode: host
      target: 443
      published: 443
    - mode: host
      target: 5432
      published: 5432
    - mode: host
      target: 5433
      published: 5433
    volumes:
    - type: bind
      source: .../traefik/config/master_dyn_cfg.yml
      target: /etc/traefik/dynamic_cfg.yml
      bind:
        create_host_path: true
    - type: bind
      source: /etc/traefik_certs
      target: /etc/traefik_certs
      bind:
        create_host_path: true
    - type: bind
      source: /var/run/docker.sock
      target: /var/run/docker.sock
      bind:
        create_host_path: true
  whoami:
    deploy:
      labels:
        traefik.docker.network: public-network
        traefik.enable: "true"
        traefik.http.routers.whoami.entrypoints: https
        traefik.http.routers.whoami.middlewares: ops_whitelist_ips@docker, ops_auth@docker,
          ops_gzip@docker
        traefik.http.routers.whoami.rule: Host(`<domain>`)
          && PathPrefix(`/whoami`)
        traefik.http.routers.whoami.tls: "true"
        traefik.http.services.whoami.loadbalancer.server.port: "80"
      resources:
        limits:
          cpus: "0.5"
          memory: "52428800"
        reservations:
          cpus: "0.1"
          memory: "6291456"
    image: containous/whoami
    networks:
      public: null
networks:
  monitored:
    name: monitored_network
    external: true
  public:
    name: public-network
    external: true

./config/master_dyn_cfg.yml

tls:
  certificates:
    - certFile: /etc/traefik_certs/<domain>.crt
      keyFile: /etc/traefik_certs/<domain>.key

/etc/traefik_certs contains the certificates listed in ./config/master_dyn_cfg.yml.

You have to replace:

by --providers.file.directory (and use a directory instead of a file)

because filename has a problem on some filesystems to detect changes.

1 Like

And don't forget to enable watch (doc)

1 Like

So, the final solution that make traefik dynamically update certificates is as follows:

  1. you must use providers.file.directory instead of providers.file.filename
  2. you must use providers.file.watch=true
  3. to trigger traefik update you must touch the dynamic config or the mounted directory itself

docker-compose.yml

version: '3.7'
services:
  traefik:
    command:
      ...
      - "--providers.file.directory=/etc/traefik/"
      - "--providers.file.watch=true"
    env_file:
      - .env
    volumes:
    - /etc/traefik_certs:/etc/traefik_certs
    - ./config/master/:/etc/traefik/

./config/master/dynamic_config.yml

tls:
  certificates:
    - certFile: /etc/traefik_certs/<domain>.crt
      keyFile: /etc/traefik_certs/<domain>.key

I will attach a good guide here. It has one flaw: it doesn't mention that you must touch dynamic config to trigger traefik to update certificates. The guide: Traefik Proxy 2.x and TLS 101 [Updated 2022] | Traefik Labs

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