Traefik is a popular reverse proxy and load balancer often used to manage incoming traffic to applications running in Docker containers and Kubernetes environments. One of the benefits of using Traefik is the ability to set up automatic SSL certificates using letsencrypt, making it easier to manage SSL-encrypted websites.
Let’s look at Traefik Letsencrypt certificates configuration with Traefik and Letsencrypt certificates. You need to be familiar with Docker and Traefik in general and have a working Docker environment setup with Docker Compose installed. Also, understanding how to read basic YML file configurations will help.
What is Letsencrypt?
Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG). It takes the cost and complexity out of SSL certificates so everyone can benefit from securing HTTPS resources with proper certificate resources.
About This Docker Traefik Stack
We use a Docker Traefik stack to manage incoming application traffic. This stack consists of two Docker containers: Traefik, which will act as our reverse proxy and load balancer, and a media server container (in this case, the Linux server Plex container), which Traefik will manage.
Differences From Traefik v1
This guide covers Traefik v2, which has some differences in configuration compared to previous versions of Traefik.
Objectives of this Traefik 2 Docker Home Server Setup
This Traefik 2 Docker Home Server setup aims to create a reverse proxy and load balancer to manage incoming traffic to our media server container. We will use Letsencrypt to automatically generate SSL certificates for our applications and configure basic HTTP authentication to secure our media server.
Traefik Reverse Proxy Overview
Traefik is a popular reverse proxy, and load balancer often used to manage incoming traffic to applications running in Docker containers. Traefik can automatically detect new containers in your Docker environment and route traffic to the appropriate container based on the container’s labels.
Traefik Setup
To get started with Traefik v2, we must create a new Docker Compose file for our Traefik stack. This file will define the configuration for our Traefik service.
version: "3"
services:
traefik:
image: traefik:v2.5
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
environment:
- CF_API_EMAIL=<cloudflare email>
- CF_API_KEY=<cloudflare api key>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/letsencrypt:/letsencrypt
- /opt/traefik/traefik.yml:/traefik.yml
networks:
- traefik
networks:
traefik:
external: true
In this configuration, we are defining a new service called traefik, which uses the traefik:v2.5 image. We are also mounting the Docker socket and the letsencrypt and traefik.yml files as volumes, and defining the traefik network as an external network for the Traefik container.
Prepare Traefik 2 Folders and Files
In the previous section, we created a docker-compose.yml file for our Traefik Docker stack. Now, let’s create the necessary folders and files for Traefik to use.
First, we need to create a file called traefik.yml in the same directory as our docker-compose.yml file. This file will define the static configuration for our Traefik service:
providers:
docker:
exposedByDefault: false
file:
filename: /etc/traefik/dynamic.yml
http:
routers:
dashboard:
rule: Host(`traefik.<your domain>`)
service: api@internal
middlewares:
- traefik-auth
tls:
certResolver: dns-cloudflare
middlewares:
traefik-auth:
basicAuth:
users:
- "<username>:<password>"
certificatesResolvers:
dns-cloudflare:
acme:
email: <your email>
storage: /letsencrypt/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 0
caServer: https://acme-v02.api.letsencrypt.org/directory
In this configuration, we are defining a new provider In this configuration, we are defining a new provider called file, which will load the dynamic configuration for our Traefik service from a file called dynamic.yml. We are also defining a new router called dashboard, which will route traffic to the Traefik dashboard.
We are also defining a middleware called traefik-auth, which uses basic HTTP authentication to secure the Traefik dashboard. We have also defined a certificate resolver called dns-cloudflare for the DNS challenge, which will automatically generate Letsencrypt SSL certificates using the Cloudflare DNS provider.
You will see in the config above the acme certificates are stored in the acme certificates json file. The acme.json file stores the actual certificates pulled after the acme-challenge to Letsencrypt certificate resolver for the SSL certificate.
Letsencrypt certificate server to use
An important configuration when you are developing your docker-compose file and testing your Letsencrypt configuration is to point to the letsencrypt acme staging v02 api.letsencrypt.org server.
There is a rate limit on the production server that you will hit if you keep testing your configuration and pulling certificates from the certificate resolver.
During testing and development of your Docker-compose code, use the staging v02 api.letsencrypt.org directory server and then when you have everything lined out from a configuration perspective, you can transition over to the production server as the staging server does not have the rate limits that exist on the production server.
Static Configuration
In addition to the traefik.yml file, we also need to create a new file called dynamic.yml. This file will define the dynamic configuration for our Traefik service, including the routers, middlewares, and services for our media server container.
http:
routers:
plex:
rule: Host(`plex.<your domain>`)
entryPoints:
- https
middlewares:
- plex-auth
service: plex-svc
tls:
certResolver: dns-cloudflare
middlewares:
plex-auth:
basicAuth:
users:
- "<username>:<password>"
services:
plex-svc:
loadBalancer:
servers:
- url: "http://plex:32400"
In this configuration, we are defining a new router called plex, which will route traffic to our media server container using the domain name plex.<your domain>. We also define a middleware called plex-auth, which uses basic HTTP authentication to secure the media server.
We are also defining a new service called plex-svc, which will load balance traffic to the plex container.
Traefik 2 Routers, Middlewares, and Services
In Traefik, we can use routers to route traffic to our applications, middlewares to modify incoming requests and responses, and services to load balance traffic to our containers.
In the previous section, we defined a new router called plex to route traffic to our media server container. We also defined a middleware called plex-auth to secure the media server, and a service called plex-svc to load balance traffic to the plex container.
Define Trusted IPs
In addition to basic HTTP authentication, we can also define a list of trusted IP addresses that can access our Traefik dashboard without authentication. To do this, we need to add a new label to our Traefik service:
labels:
- "traefik.http.middlewares.traefik-auth.ipWhiteList.sourceRange=192.168.0.0/16"
In this example, we are allowing all IP addresses from the 192.168.0.0/16 subnet to access the Traefik dashboard without authentication. You can modify this value to allow specific IP addresses or subnets to access the dashboard.
Docker Network
Before we can start our Traefik stack, we need to define a new Docker network that our Traefik and media server containers will use:
docker network create traefik
This will create a new Docker network called traefik.
Define Networks for Traefik Docker Compose
Now, we can update our docker-compose.yml file to include the new Docker network for the internal networks we will use when we expose containers using Traefik. Note you can also use an env file to contain configuration values for the variables.
version: "3"
services:
traefik:
image: traefik:v2.5
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
environment:
- CF_API_EMAIL=<cloudflare email>
- CF_API_KEY=<cloudflare api key>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/letsencrypt:/letsencrypt
- /opt/traefik/traefik.yml:/traefik.yml
networks:
- traefik
- default
plex:
image: linuxserver/plex
container_name: plex
restart: unless-stopped
environment:
- PUID=<your user ID>
- PGID=<your group ID>
- TZ=<your timezone>
volumes:
- /opt/plex:/config
- /mnt/disks/media:/data
networks:
- traefik
- default
networks:
traefik:
external: true
In this configuration, we have added the traefik network to both the Traefik and media server containers. We have also defined a new network called default, the default Docker network.
Testing Docker Traefik 2 Setup
Now that we have defined our Docker Traefik 2 setup, we can start our Traefik stack and media server container by running the following command:
docker-compose up -d
This will start our Traefik stack and media server container in detached mode.
Start Adding Docker Media Server Containers
With our Traefik stack set up and running, we can now add additional media server containers. We need to define a new service in our docker-compose.yml file with the appropriate labels.
Add Docker Compose for Traefik v2
In addition to our media server containers, we can add other Docker applications to our Traefik stack. We must define a new service in our docker-compose.yml file with the appropriate labels.
Create Traefik 2 Environmental Variables
We can define environmental variables in our docker-compose.yml file to configure our Traefik service. For example, we can define the email address to use for Letsencrypt SSL certificates so we can read the DNS records in the Cloudflare environment when we enable Traefik:
environment:
- CF_API_EMAIL=<cloudflare email>
- CF_API_KEY=<cloudflare api key>
With the above, we use the global API key for our DNS zone to authenticate to Cloudflare and read the DNS records.
Traefik 2 Basic HTTP Authentication – Middleware
As mentioned earlier, we can use middleware in Traefik to modify incoming requests and responses. One useful middleware is the basicauth middleware, which allows you to add basic HTTP authentication to your applications.
To use the basicauth middleware, we need to define a new middleware in our Traefik configuration file:
middlewares:
my-auth:
basicAuth:
users:
- "user:password"
In this example, we define a new middleware called my-auth, which uses basic HTTP authentication to authenticate users with the username and password. We can then apply this middleware to our routers or services as needed.
Redirect to HTTPS
To ensure that all traffic to our applications is encrypted, we can configure Traefik to redirect all HTTP traffic to HTTPS. To do this, we need to add a new middleware to our Traefik configuration file:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
We can then apply this middleware to our routers or services to redirect all HTTP traffic to HTTPS.
Tip to Identify Copy-Paste Errors
When copying and pasting configuration files, it is easy to introduce errors accidentally. To help identify these, we can use the traefik check command to check the syntax of our Traefik configuration files:
traefik check
This command will check the syntax of our configuration files and report any errors or warnings.
Networks for Traefik 2 Dashboard
By default, the Traefik dashboard is only accessible from the host machine. To access the dashboard from another machine on the network, we need to modify our Traefik configuration to bind the dashboard to a specific IP address or network interface.
providers:
docker:
exposedByDefault: false
http:
routers:
dashboard:
rule: Host(`traefik.<your domain>`)
service: api@internal
middlewares:
- traefik-auth
tls:
certResolver: dns-cloudflare
middlewares:
traefik-auth:
basicAuth:
users:
- "<username>:<password>"
certificatesResolvers:
dns-cloudflare:
acme:
email: <your email>
storage: /letsencrypt/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 0
caServer: https://acme-v02.api.letsencrypt.org/directory
api:
dashboard: true
debug: true
insecure: true
# Uncomment the following lines to bind the dashboard to a specific IP address or network interface
# address: 192.168.0.10
# entryPoints:
# - http
In this example, we have added the api section to our Traefik configuration, which includes the dashboard, debug, and insecure settings. We have also commented out the address and entryPoints settings, which can be used to bind the dashboard to a specific IP address or network interface.
We are also specifying the Host rule for the router, which is set to traefik.<your domain>. This means that the Traefik dashboard will be accessible at https://traefik.<your domain>.
We are using the basicAuth middleware to add basic HTTP authentication to the Traefik dashboard. We have defined a new middleware called traefik-auth, which uses the basicAuth middleware to authenticate users with the specified username and password.
The certificatesResolvers section defines the dns-cloudflare certificates resolver, which is used to fetch and manage LetsEncrypt SSL certificates using the Cloudflare DNS provider. We are also specifying the email address to use for LetsEncrypt SSL certificates and the storage location for the certificates.
The api section includes the dashboard, debug, and insecure settings. The dashboard setting enables the Traefik dashboard, the debug setting enables debug logging, and the insecure setting allows insecure connections to the dashboard.
Finally, we have commented out the address and entryPoints settings, which can be used to bind the dashboard to a specific IP address or network interface. If you want to bind the dashboard to a particular IP address or network interface, you can uncomment these lines and update the values as needed.
Fetching Real LetsEncrypt Wildcard Certificates using Traefik
To fetch real LetsEncrypt wildcard certificates using Traefik, we need to configure our DNS provider with the appropriate API keys. In this example, we are using the Cloudflare DNS provider, but you can use any supported DNS provider.
You can find the list of supported providers here:
First, we must create a new Cloudflare API token with the MyProfile > API Tokens> Create Token.
We can then add the following environment variables to our Traefik service:
environment:
- CF_API_EMAIL=<cloudflare email>
- CF_API_KEY=<cloudflare api key>
We also need to update our Traefik configuration file to use the dnsChallenge settings:
certificatesResolvers:
dns-cloudflare:
acme:
email: <your email>
storage: /letsencrypt/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 0
In this configuration, we are defining a new certificates resolver called dns-cloudflare that uses the Cloudflare DNS provider. We are also specifying the email address to use for LetsEncrypt SSL certificates and the storage location for the certificates.
We use the dnsChallenge settings to verify domain ownership by adding a DNS TXT record to our Cloudflare account. Traefik will automatically create and remove this record during certificate renewal.
Finally, we are adding the CF_API_EMAIL and CF_API_KEY environment variables to our Traefik service, which are used to authenticate with the Cloudflare API.
Middleware Chains
Traefik 2 supports middleware chains, which allow us to apply multiple middlewares to a single router or service. To use middleware chains, we need to define a new middleware that references the other middlewares:
middlewares:
my-auth-chain:
chain:
middlewares:
- middleware1
- middleware2
- middleware3
In this example, we are defining a new middleware called my-auth-chain, which includes the middleware1, middleware2, and middleware3 middlewares. We can then apply the my-auth-chain middleware to our routers or services.
Adding Apps to Traefik Docker Compose Stack
With our Traefik Docker Compose stack set up, we can easily add new applications by defining a new service in our docker-compose.yml file with the appropriate labels.
services:
app1:
image: app1:latest
container_name: app1
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.app1.rule=Host(`app1.<your domain>`)"
- "traefik.http.routers.app1.tls.certresolver=dns-cloudflare"
- "traefik.http.middlewares.app1-auth.basicauth.users=<username>:<password>"
- "traefik.docker.network=traefik"
networks:
- traefik
- default
In this example, we are defining a new service called app1 with the appropriate labels. The traefik.enable label tells Traefik to enable routing for this application. The traefik.http.routers.app1. The rule label defines this application’s router rule, and the traefik.http.routers.app1.tls.certresolver label specifies the certificate resolver to use.
We are also defining a new middleware called app1-auth, which uses basic HTTP authentication to secure the application. Finally, we are adding the traefik.docker.network label to specify the network to use.
–certificatesResolvers.dns-cloudflare.acme Lines
The certificatesResolvers.dns-cloudflare.acme lines in our Traefik configuration file are responsible for fetching and managing LetsEncrypt SSL certificates using the Cloudflare DNS provider.
In this configuration, we define a new certificate resolver called dns-cloudflare that uses the Cloudflare DNS provider. We are also specifying the email address to use for LetsEncrypt SSL certificates and the storage location for the certificates.
Other Apps
In addition to media server containers, we can use Traefik to route traffic to other Docker applications. Some popular applications that can be used with Traefik include:
Plex
Jellyfin
Nextcloud
Home Assistant
Bitwarden
Adding non-docker or external apps behind Traefik
Traefik can also route traffic to non-Docker, external applications, or web servers. To do this, we need to define a new service in our docker-compose.yml file with the appropriate labels:
services:
external-app:
container_name: external-app
image: nginx:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.external-app.rule=Host(`external.<your domain>`)"
- "traefik.http.routers.external-app.tls.certresolver=dns-cloudflare"
- "traefik.http.middlewares.external-app-auth.basicauth.users=<username>:<password>"
networks:
- traefik
- default
In this example, there is a new service called external-app with the appropriate labels. The traefik.enable label tells Traefik to enable routing for this application. The traefik.http.routers.external-app.rule label defines the router rule for this application, and the traefik.http.routers.external-app.tls.certresolver label specifies the certificate resolver to use.
We also define middleware called external-app-auth, which uses basic HTTP authentication to secure the application. Finally, we are adding the traefik.docker.network label to specify the network to use.
Wrapping up
Using Traefik along with Cloudflare and Letsencrypt is a great way to secure your web resources and ensure you have proper certificates protecting your web servers in your environment. With Traefik and Letsencrypt automation, you can have Letsencrypt automatically renew your certificates without the tedious manual processes this typically requires.
0 Comments