How to setup Traefik v2 with automatic Let’s Encrypt certificate resolver

Illustration by author of components used to achieve the goal

How to setup Traefik v2 with automatic Let’s Encrypt certificate resolver

Today it is really important to have SSL encrypted websites. This guide will show how easy it is to have an automatic SSL resolver built into your traefik load balancer.

Paul Knulst  in  Docker Nov 14, 2021 3 min read

Today it is really important to have SSL encrypted websites. This guide will show how easy it is to have an automatic SSL resolver built into your traefik load balancer.

After I learned how to docker, the next thing I needed was a service to help me organize my websites. This is why I learned about traefik which is a:

Cloud-Native Networking Stack That Just Works

One important feature of traefik is the ability to create Let’s Encrypt SSL certificates automatically for every domain which is managed by traefik.

Then I started to research…

https://www.knulst.de/how-to-setup-traefik-with-automatic-letsencrypt-certificate-resolver
Me sitting in front of my computer researching

I tested several configurations and created my own traefik instances on my local machine until I came up with this docker-compose.yml:

version: "3.3"
services:
  traefik:
    image: "traefik:v2.2.1"
    container_name: traefik
    hostname: traefik
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker
      - --providers.docker.exposedByDefault=false
      - --api
      - --certificatesresolvers.le.acme.email=${TRAEFIK_SSLEMAIL?Variable not set}
      - --certificatesresolvers.le.acme.storage=./acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./acme.json:/acme.json"
    labels:
      - "traefik.enable=true"
      # Dashboard
      - "traefik.http.routers.traefik.rule=Host(`dashboard.${PRIMARY_DOMAIN}`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.tls.certresolver=le"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.middlewares=authtraefik"
      - "traefik.http.middlewares.authtraefik.basicauth.users=devAdmin:$2y$05$h9OxLeY20/5uiXjfPgdRxuFlrfqBf2QifYDgrwsR6rAEgX3/dpOGq" # user:devAdmin, password:devto
      # global redirect to https
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    restart: unless-stopped
    networks:
      - traefik-public
  my-app:
    image: containous/whoami:v1.3.0
    hostname: whoami
    container_name: whoami
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.my-app.rule=Host(`whoami.${PRIMARY_DOMAIN}`)"
      - "traefik.http.routers.my-app.middlewares=auth"
      - "traefik.http.routers.my-app.entrypoints=websecure"
      - "traefik.http.routers.my-app.tls=true"
      - "traefik.http.routers.my-app.tls.certresolver=le"
      - "traefik.http.middlewares.auth.basicauth.users=devAdmin:$2y$05$h9OxLeY20/5uiXjfPgdRxuFlrfqBf2QifYDgrwsR6rAEgX3/dpOGq" # user:devAdmin, password:devto
    networks:
      - traefik-public:
networks:
  traefik-public:
    external: true

This file contains several important sections:

  1. Two entry points web (Line 8) and websecure (Line 9) which are used for http and https
  2. Enabling docker (Line 10) but not publishing every container by default (Line 11)
  3. Activate API (with URL defined in labels) (Line 12)
  4. Certificate handling. Defining an info email (Line 13), set a storage acme.json (Line 14), activating TLS (Line 15)
  5. Exposing port for HTTP (Line 17) and HTTPS (Line 18)
  6. Within the volumes section, the docker-socket will be mounted into traefik container (Line 20) and the acme.json is mounted into the local filesystem (Line 21)
  7. Enable traefik for this service (Line 23). This has to be done because no service is exported by default (see Line 11)
  8. Add the dashboard domain (Line 25), define a service (Line 26), activate TLS (Line 27) with a prior defined certificate resolver (Line 28), and set the websecure entry point (Line 29)
  9. Activate HTTP - Basic Auth middleware (Line 30)which will be “created” in the next line
  10. Creating the traefik dashboard which is encrypted with HTTP - Basic Auth (Line 31)
  11. Global redirect to HTTPS is defined and activation of the middleware (Line 32 - 37)
  12. To test I defined another service whoami just to show some data and test the SSL certificate creation (Line 41 - Line 55)

Before running the docker-compose.yml a network has to be created! This is necessary because within the file an external network is used (Line 56–58). This is important because the external network traefik-public will be used between different services.

The external network is created with:

docker network create traefik-public

The last step is exporting the needed variables and running the docker-compose.yml:

export PRIMARY_DOMAIN=yourdomain.de
export TRAEFIK_SSLEMAIL=youremai@yourdomain.de

docker-compose up -d

The commands above will now create two new subdomains (https://dashboard.yourdomain.de and https://whoami.yourdomain.de) which also use an SSL certificate provided by Let’s Encrypt

Finally finish setting up the Traefik v2 within your Docker environment
Photo by Eden Constantino / Unsplash

I hope this article gave you a quick and neat overview of how to set up traefik

Code-wise a lot of improvements can be made. However, with the current very limited functionality it is enough. It is more about customizing new commands, but always focusing on the least amount of sources for the truth.

Happy Dockering! 🥳 👨🏻‍💻

Feel free to connect with me on Medium, LinkedIn, and Twitter.


🙌 Support this content

If you like this content, please consider supporting me. You can share it on social media, buy me a coffee, or become a paid member. Any support helps.

See the contribute page for all (free or paid) ways to say thank you!

Thanks! 🥰

By Paul Knulst

I'm a husband, dad, lifelong learner, tech lover, and Senior Engineer working as a Tech Lead. I write about projects and challenges in IT.