Traefik can provide TLS certificates for your services automatically, eliminating manual renewal and configuration headaches.

Let’s see it in action with a simple setup. Imagine you have a Traefik instance running and you want to expose a web service, say a simple "hello world" app running on localhost:8080.

# docker-compose.yml
version: '3.7'

services:
  traefik:
    image: traefik:v2.10
    command:
      - --api.insecure=true # For demonstration, disable in production
      - --providers.docker=true
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myresolver.acme.email=your-email@example.com # Replace with your email
      - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt # Traefik will store certificates here
    restart: unless-stopped

  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)" # Replace with your domain
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

In this docker-compose.yml:

  • The traefik service is configured to listen on port 443 (entrypoints.websecure.address=:443).
  • It defines a certificate resolver named myresolver that uses ACME (the protocol Let’s Encrypt uses).
  • certificatesresolvers.myresolver.acme.email is crucial for Let’s Encrypt to contact you about your certificates.
  • certificatesresolvers.myresolver.acme.storage points to a file (acme.json) where Traefik will store the obtained certificates. This file needs to be writable by Traefik.
  • certificatesresolvers.myresolver.acme.tlschallenge=true tells Traefik to use the TLS-ALPN challenge, which is generally preferred and often less prone to network issues than the HTTP-01 challenge.
  • The whoami service is a simple demo app.
  • Crucially, the labels on whoami tell Traefik:
    • To enable routing for it (traefik.enable=true).
    • To create a router that matches requests for whoami.localhost (traefik.http.routers.whoami.rule=Host(\whoami.localhost`)).
    • That this router should use the websecure entrypoint (port 443) (traefik.http.routers.whoami.entrypoints=websecure).
    • And most importantly, that it should use the myresolver to obtain and manage TLS certificates for this router (traefik.http.routers.whoami.tls.certresolver=myresolver).

When you run docker-compose up -d, Traefik will start. When a request comes in for whoami.localhost on port 443, Traefik will see the tls.certresolver=myresolver label. It will then attempt to obtain a certificate for whoami.localhost from Let’s Encrypt using the configured resolver. If successful, it will serve the certificate and forward the request to the whoami service. The certificate and its private key will be saved in ./letsencrypt/acme.json.

The problem Traefik’s automatic TLS setup solves is the operational burden of managing TLS certificates. Traditionally, this involves: obtaining a certificate from a Certificate Authority (CA), uploading it to your web server, configuring the web server to use it, and then meticulously tracking its expiration date to renew it before it expires, which can cause outages. Traefik automates all of this by integrating directly with Let’s Encrypt. It handles the ACME challenges, certificate acquisition, renewal, and application to the defined routes.

Internally, Traefik acts as an ACME client. When a router is configured to use a certificate resolver and receives a request for a domain it doesn’t have a valid certificate for, Traefik initiates the ACME process. For the TLS-ALPN challenge, it essentially tells Let’s Encrypt, "I’m ready to receive a certificate for yourdomain.com on port 443." Let’s Encrypt then connects to Traefik on port 443 and performs a challenge to verify that Traefik controls the domain. If the challenge passes, Let’s Encrypt issues a certificate, which Traefik then stores and uses. Traefik polls its stored certificates and automatically renews them well before they expire, typically around 30 days before expiration.

The exact levers you control are primarily within the certificatesresolvers configuration in Traefik’s static configuration and the tls.certresolver label on your services. You define the ACME server endpoint (usually Let’s Encrypt’s production or staging URL), the email for notifications, the storage location, and the challenge type. On the dynamic configuration side (service labels), you associate specific routers with a certificate resolver. You can also configure multiple certificate resolvers for different needs (e.g., one for Let’s Encrypt, another for a private CA).

A common pitfall is trying to use localhost or private IP addresses with Let’s Encrypt. Let’s Encrypt only issues certificates for publicly resolvable domain names. If you’re testing locally, you should use a domain that you own and point it to your Traefik instance using your /etc/hosts file (for local testing only) or DNS records. For example, you might set 127.0.0.1 myapp.mydomain.com in your /etc/hosts file and configure Traefik to use Host(\myapp.mydomain.com`)`.

The next concept you’ll likely explore is advanced routing rules and middleware, allowing you to apply complex logic before requests reach your services.

Want structured learning?

Take the full Traefik course →