Default TLS configuration for a Lets Encrypt wildcard certificate

Greetings! :ringer_planet:

Thank You very much for the awesome project and service!


I am trying configuring the default certificate Traefik would redirect in case of non-configured nor non-existent path or subdomain.

Following the documentation, it seems a dynamic configuration is required for tls root directive. There is
a Yaml for this case here which is located in the directory stated in the main static Traefik File provider directory setting.

The few questions which rose are the following:

  1. Should it be domains or domain in tls.stores.default.defaultGeneratedCert dynamic File provider configuration file root setting alongside resolver? To be exact, TLS -> ACME Default Certificate vs. Let's Encrypt ACME Provider -> Domain Definition.

  2. Is the following a typo or custom Traefik syntax?:

tls:
  certResolver: myresolver
  domains: # Or `domain`?
    - main: "example.org"
      sans: # The YAML "dash" is missing?
        - "*.example.org"

Current Example Configuration

A dynamic configuration file /etc/traefik/providers/tls.yaml in File provider stated directory /etc/traefik/providers is the following:

tls:
  stores:
    default:
      defaultGeneratedCert:
        resolver: 'lets-encrypt'
        domain:
          main: 'example.com'
          sans:
            - '*.example.com'

The static configuration file /traefik.yaml:

entryPoints:
  http:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: 'https'
          scheme: 'https'
  https:
    address: ':443'
    http:
      tls:
        certResolver: 'lets-encrypt'
  traefik:
    address: ':8001'

defaultEntryPoints:
  - 'http'
  - 'https'

# @see https://doc.traefik.io/traefik/https/acme/#certificate-resolvers
certificatesResolvers:
  lets-encrypt:
    acme:
      email: 'example@example.com'
      storage: '/resolvers/acme.json'
      keyType: 'RSA4096'
      preferredChain: 'ISRG Root X1'
      httpChallenge:
        entryPoint: 'http'

# @see https://doc.traefik.io/traefik/v2.0/providers
providers:
  file:
    directory: '/etc/traefik/providers'
    watch: true
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    watch: true
    network: 'reverse-proxy'
    exposedByDefault: false

api:
  insecure: true
  dashboard: true
  debug: true

log:
  filePath: '/var/log/traefik/traefik.log'
  level: 'DEBUG'

accessLog:
  filePath: '/var/log/traefik/access.log'

An error on Traefik restart:

time="2023-10-19T09:37:07Z" level=debug msg="Using HTTP Challenge provider." providerName=lets-encrypt.acme                                                                              
time="2023-10-19T09:37:07Z" level=debug msg="legolog: [INFO] [*.example.com, example.com] acme: Obtaining bundled SAN certificate"                                                         
time="2023-10-19T09:37:08Z" level=debug msg="legolog: [INFO] [*.example.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/1"                                    
time="2023-10-19T09:37:08Z" level=debug msg="legolog: [INFO] [example.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/2"                                      
time="2023-10-19T09:37:08Z" level=debug msg="legolog: [INFO] [example.com] acme: authorization already valid; skipping challenge"                                                         
time="2023-10-19T09:37:08Z" level=debug msg="legolog: [INFO] [*.example.com] acme: Could not find solver for: dns-01"                                                                     
time="2023-10-19T09:37:09Z" level=debug msg="legolog: [INFO] Skipping deactivating of valid auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/1"                       
time="2023-10-19T09:37:09Z" level=debug msg="legolog: [INFO] Deactivating auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/2"                                         
time="2023-10-19T09:37:09Z" level=debug msg="Serving default certificate for request: \"\"" 
time="2023-10-19T09:37:09Z" level=error msg="Unable to obtain ACME certificate for domain \"*.example.com,example.com\"" ACME CA="https://acme-v02.api.letsencrypt.org/directory" tlsStoreName=default error="unable to generate a certificate for the domains [*.example.com example.com]: error: one or more domains had a problem:\n[*.example.com] [*.example.com] acme: could not determine solvers\n" providerName=lets-encrypt.acme

An error with a GET request at test.example.com:

time="2023-10-19T10:17:08Z" level=debug msg="Serving default certificate for request: \"\""
time="2023-10-19T10:19:53Z" level=debug msg="Serving default certificate for request: \"\""
time="2023-10-19T10:21:57Z" level=debug msg="Serving default certificate for request: \"test.example.com\""
time="2023-10-19T10:21:57Z" level=debug msg="Serving default certificate for request: \"test.example.com\""
time="2023-10-19T10:21:57Z" level=debug msg="http: TLS handshake error from 100.101.102.103:58010: remote error: tls: unknown certificate"
time="2023-10-19T10:21:57Z" level=debug msg="http: TLS handshake error from 100.101.102.103:57998: remote error: tls: unknown certificate"
time="2023-10-19T10:21:57Z" level=debug msg="Serving default certificate for request: \"test.example.com\""
time="2023-10-19T10:21:57Z" level=debug msg="http: TLS handshake error from 100.101.102.103:58024: remote error: tls: unknown certificate"

The requests results in the internal certificate: TRAEFIK DEFAULT CERT.

DNS has the following records shown in dig:

id: 12345
opcode: QUERY
status: NOERROR
flags: QR RD RA CD
;; QUESTION SECTION:
;example.com.		IN A
;; ANSWER SECTION:
example.com.		180 IN A 100.101.102.103

The hosting providers has the following set:

+------+------+-----------------+
| Type | Host | Value           |
+------+------+-----------------+
| A    | @    | 100.101.102.103 |
| A    | *    | 100.101.102.103 |
+------+------+-----------------+

Is it possible to have a wildcard certificate for such a redirect? At least for the first 3 subdomains? What if someone would try surfing a 4th subdomain when Let's Encrypt does not offer it? Would it reveal the default Traefik one anyways, and if so, is it possible to block traffic in case of non-existing subdomain/configuration at all?

Best and kind regards :sparkles:

Check the dynamic config file reference.