I got the question how to configure multiple domains in Traefik when one of the domains is a network internal domain without the possibility for a Let’s Encrypt certificate. Actually, it’s pretty easy: Just add your services. Let’s look at an example.

Multiple Domains

Traefik will discover your services using the method you specified in the configuration file. There are several discovery variants available. Here, we will use auto discovery on docker containers.
When Traefik encounters a Docker container it will read the labels of the container to deduct the domain the service shall run on and wether or not you want to use TLS. When you enable the Let’s Encrypt certificate resolver beforehand and set the right labels, the new domain with TLS will just work.

Entrypoint And Resolver

Traefik wants to know on which IPs and ports it has to listen on. In Traefik terms, such an IP/port combination is called an entrypoint. We need two entrypoints on port 80 and 443. We will use 443 for the TLS traffic and 80 to obtain certificates from Let’s Encrypt. The following snippet must go into the main config file:

/etc/traefik/traefik.yml
entryPoints:
web:
# Listen on all addresses and port 80
address: ":80"
websecure:
address: ":443"

Then we have to tell Traefik to store certificates and activate the Let’s Encrypt resolver. The resolver will obtain a certificate for the domains we enable it for. Notice how we reference the web entrypoint that we added before. We tell the resolver to use it to answer the challenges necessary to obtain a certificate. Add this to your Traefik config file:

/etc/traefik/traefik.yml
tls:
stores:
default: {}
certificatesResolvers:
letsEncryptResolver:
acme:
# Use a proper email address
email: admin@example.com
storage: /etc/traefik/acme.json
httpChallenge:
entryPoint: web

Docker Compose Configuration

Suppose you want to run two containers. One with a blog from blog.example.com and a wiki from wiki.example.com. Add a labels section to each service in your docker compose file and add your configuration. Traefik will read these labels and act accordingly.

version: "3.9"
services:
blog:
# container specs go here
labels:
# first, from which domain do you want to serve this container?
- "traefik.http.routers.blog.rule=Host(`blog.example.com`)"
# switch on TLS
- "traefik.http.routers.blog.tls=true"
# tell Traefik to serve it from port 443
- "traefik.http.routers.blog.entrypoints=websecure"
# Traefik shall get a certificate using the letsEncryptResolver
- "traefik.http.routers.blog.tls.certresolver=letsEncryptResolver"
wiki:
labels:
- "traefik.http.routers.wiki.rule=Host(`wiki.example.com`)"
- "traefik.http.routers.wiki.tls=true"
- "traefik.http.routers.wiki.entrypoints=websecure"
- "traefik.http.routers.wiki.tls.certresolver=letsEncryptResolver"

Ansible Configuration

The same example as before, just for when you want to use ansible tasks. Here, the labels are actual yaml key/value pairs. So you have to put quotation marks around the boolean values.

- name: Ensure blog
docker_container:
# container specs go here
labels:
traefik.http.routers.blog.rule: "Host(`blog.example.com`)"
traefik.http.routers.blog.tls: "true"
traefik.http.routers.blog.entrypoints: "websecure"
traefik.http.routers.blog.tls.certresolver: letsEncryptResolver

- name: Ensure wiki
docker_container:
# container specs go here
labels:
traefik.http.routers.wiki.rule: "Host(`wiki.example.com`)"
traefik.http.routers.wiki.tls: "true"
traefik.http.routers.wiki.entrypoints: "websecure"
traefik.http.routers.wiki.tls.certresolver: letsEncryptResolver

Custom Certificates

Traefik will automatically use a provided certificate when you tell it to switch TLS on but don’t specify a certificate resolver. You might want to use a custom certificate for extra security or on your local network where you cannot obtain a certificate from Let’s Encrypt.
But Traefik has to know about the certificate first. It will read certificate locations from its dynamic configuration. We configure it to watch the directory /etc/traefik/dynamic for new or changed dynamic configuration files.

/etc/traefik/traefik.yml
providers:
file:
directory: /etc/traefik/dynamic
watch: true

Then we put a list of the locations of our custom certificates into a file and save it to the /etc/traefik/dynamic directory. Traefik will read the certificate, determine the domain name it is for and use it for our service above.

/etc/traefik/dynamic/traefik-dynamic.yml
---
tls:
certificates:
- certFile: /etc/traefik/tnglab.fritz.box.crt
keyFile: /etc/traefik/tnglab.fritz.box.key
...

If you have more certificates later on, just update the file. Traefik will notice and check the new certificate.

Now we can start our service:

version: "3.9"
services:
tnglab:
labels:
# This service runs in our LAN
- "traefik.http.routers.tnglab.rule=Host(`tnglab.fritz.box`)"
- "traefik.http.routers.tnglab.tls=true"
- "traefik.http.routers.tnglab.entrypoints=websecure"
# Note that we are omitting the certresolver option

Traefik will look up the domain name in in the certificate store and use our custom certificate.