Trouble understanding how traefik picks up a custom SSL certificate for a domain

I am having trouble understanding the relation between the router and the provided SSL ceritifcate files. How traefik knows which certificate to choose for a particular domain.

I have got following configuration but traefik is providing a default SSL certificate. The traefik docs have largly described how to use ACME but it does not specify clearly how to use your own SSL certificates for multiple domains.

Here is my traefik.toml

[entrypoints]
  [entrypoints.http]
    address = ":80"

  [entrypoints.https]
    address = ":443"

[providers]
  [providers.docker]

[tls]

  [tlsOptions]
    [tlsOptions.default]
      minVersion = "VersionTLS12"
      sniStrict = true

  [[tls.certificates]]
    certFile = "/data/traefik/domain.io.cert"
    keyFile = "/data/traefik/domain.io.key"

and here is my YAML for docker stack.

version: '3'

services:
  reverse-proxy:
    image: traefik:v2.0
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /data/traefik/traefik.toml:/etc/traefik/traefik.toml

  whoami:
    image: containous/whoami
    labels:
      - "traefik.http.routers.route1.rule=Host(`domain.io`)"
      - "traefik.http.routers.route1.entrypoints=https"
      - "traefik.http.routers.route1.tls=true"

Hello,

In the v2 the static configuration and the dynamic configuration cannot be mixed, so:

# static configuration
# traefik.toml

[entrypoints]
  [entrypoints.http]
    address = ":80"

  [entrypoints.https]
    address = ":443"

[providers]
  [providers.docker]
  
  [providers.file]
    filename = "/etc/traefik/dyn.toml"
# dynamic configuration
# dyn.toml

[tls.options]

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

[[tls.certificates]]
  certFile = "/data/traefik/domain.io.cert"
  keyFile = "/data/traefik/domain.io.key"

Check the TLS options syntax: https://docs.traefik.io/v2.0/https/tls/#tls-options

and https://docs.traefik.io//v2.0/https/tls/#certificates-definition

version: '3'

services:
  reverse-proxy:
    image: traefik:v2.0
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /data/traefik/traefik.toml:/etc/traefik/traefik.toml
      - /data/traefik/dyn.toml:/etc/traefik/dyn.toml

  whoami:
    image: containous/whoami
    labels:
      - "traefik.http.routers.route1.rule=Host(`domain.io`)"
      - "traefik.http.routers.route1.entrypoints=https"
      - "traefik.http.routers.route1.tls=true"

dynamic configuration:

  • routers
  • middlewares
  • services
  • tls

documentation:

static configuration:

  • information about the providers to used
  • logger definition
  • ...

documentation:

1 Like

Hi @Idez

Thank you so much for responding so quickly. I have got your point that static and dynamic config can't be mixed.

I have gone through the documentation. But there seems to be something still missing for my slow mind.

Let's say we have following two certificate files for two different domains.

# Dynamic configuration

[[tls.certificates]]
  certFile = "/path/to/domain.io.cert"
  keyFile = "/path/to/domain.io.key"

[[tls.certificates]]
  certFile = "/path/to/other.io.cert"
  keyFile = "/path/to/other.io.key"

If the first certificate is valid for wildcard *.domain.io and second one is for *.other.io. Does it mean that traefik will pickup both of these certificates at the start time. Then Traefik magically knows that it has to apply the file /path/to/domain.io.cert for any routers like Host('dev.domain.io') or Host('www.domain.io') ?

Similarly it knows that it has to apply the file /path/to/other.io.cert for any routers like Host('dev.other.io') or Host('www.other.io')?

This is the part where things get confusing. For example, I can see in the documentation that we can set tls.options in routers. But not sure what's the point of having stores of certificates and how do we tell a router, which certificate or store to use?

Traefik will use main and sans from the certificate to know which certificate to use.

1 Like

Is it possible for me to add certFile and keyFile paths via docker labels?

- "traefik.http.routers.route1.tls.certificates.certFile=/data/traefik/domain.io.cert"
- "traefik.http.routers.route1.tls.certificates.keyFile=/data/traefik/domain.io.key"

Restriction

In the above example, we've used the file provider to handle these definitions. It is the only available method to configure the certificates (as well as the options and the stores).

1 Like

Thank you so much for the great help.

I am stuck so far. Here are my files but still getting the "DEFAULT TRAEFIK CERTIFICATE". Not the actual certificate.

Any idea what I am doing wrong?

# traefik.toml
[entrypoints]
  [entrypoints.http]
    address = ":80"

  [entrypoints.https]
    address = ":443"

[providers]
  [providers.docker]
  
  [providers.file]
    filename = "/etc/traefik/dyn.toml"
#dyn.toml
[tls]

  [tls.stores]
    [tls.stores.default]
      [tls.stores.default.defaultCertificate]
        certFile = "/volumes/traefik2/my.cert"
        keyFile = "/volumes/traefik2/my.key"

  [[tls.certificates]]
    certFile = "/volumes/traefik2/my.cert"
    keyFile = "/volumes/traefik2/my.key"

Docker stack file:

# stack.yml
version: '3'

services:
  reverse-proxy:
    image: traefik:v2.0
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /volumes/traefik2/traefik.toml:/etc/traefik/traefik.toml
      - /volumes/traefik2/dyn.toml:/etc/traefik/dyn.toml

  whoami:
    image: containous/whoami
    labels:
      - "traefik.http.routers.route1.rule=Host(`dev.my.io`)"
      - "traefik.http.routers.route1.entrypoints=https"
      - "traefik.http.routers.route1.tls=true"
      - "traefik.http.routers.route1.tls.domains[0].main=my.io"
      - "traefik.http.routers.route1.tls.domains[0].sans=*.my.io"

domains are used for acme.

Thanks, it fixed the other issues I had. Currently, getting an SSL error. Any help will be greatly appreciated.

t_reverse-proxy.1.j725zfl87hft@my.io    | time="2019-09-26T00:49:40Z" level=error msg="Error while creating certificate store: failed to load X509 key pair: tls: failed to find any PEM data in certificate input" tlsStoreName=default
t_reverse-proxy.1.j725zfl87hft@my.io    | time="2019-09-26T00:49:40Z" level=error msg="Unable to append certificate /volumes/traefik2/fullchain.crt to store: unable to generate TLS certificate : tls: failed to find any PEM data in certificate input" tlsStoreName=default

Although I can verify from openssl command that my certFile is a valid file.

root@my:/volumes/traefik2# openssl crl2pkcs7 -nocrl -certfile fullchain.crt | openssl pkcs7 -print_certs -noout
subject=OU = Domain Control Validated, CN = *.my.io
issuer=C = BE, O = GlobalSign nv-sa, CN = AlphaSSL CA - SHA256 - G2

subject=C = BE, O = GlobalSign nv-sa, CN = AlphaSSL CA - SHA256 - G2
issuer=C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA

subject=C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
issuer=C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA

Below is the format of the contents of my fullchain.crt

-----BEGIN CERTIFICATE-----
(Primary SSL certificate: domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Intermediate certificate: DigiCertCA.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----

If your cert is valid and traefik complains that it's not, then chances are that you are not giving traefik the same file you think you are giving. I suggest, using alpine traefik container, and exec'ing into it to prove that.

1 Like

@zespri the v2 is only available as an alpine flavor.

Note don't use tags like v2.0-alpine, v2.0.0-alpine ,alpine, ...

2 Likes

Thank you both of you..:+1::+1: These tips have helped me resolving the issue. The SSL issue was in the volume path.

2 Likes

Hi, Can I ask what you set the volume path? I am getting the same error.

Edward

Hi just want to get info how did you resolve this when you say volume path?

These are my file paths in Linux:

/volumes/traefik/traefik.toml
/volumes/traefik/dyn.toml

Here is how dyn.toml path looks like inside my traefik.toml

  [providers.file]
    filename = "/etc/traefik/dyn.toml"
    watch = true

So, I guess if we keep the SSL files where traefik.toml is, then we can write paths in traefik.toml like:

[[tls.certificates]]
  certFile = "/etc/traefik/domain.io.cert"
  keyFile = "/etc/traefik/domain.io.key"