This post tends to give you some custom configuration files to work with Traefik and TLS.
Goal : Configure Traefik with custom TLS settings
Debian 11.2 (bullseye),
docker-compose configuration file
Forward, you can't use the two types of configuration (static and dynamic) at the same time, it is only once. I prefer dynamic configuration, here's a quick reminder.
Let's prepare the
--- services: traefik: image: traefik:v2.6 restart: unless-stopped ports: - 80:80 - 443:443 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./conf/traefik.yml:/etc/traefik/traefik.yml:ro - ./conf/traefikdynamic:/etc/traefik/dynamic:ro - ./acme.json:/etc/traefik/acme.json - ./logs/traefik.log:/etc/traefik/applog.log
- I'm using Traefik v2.6
- exposition of TPC ports 80 and 443
- Mount several volumes : a configuration file “traefik.yml” for basic options and a folder for dynamic options. The folder is mounted with its files inside.
- “acme.json” file need to be created before using it, with
touch acme.json && chmod 0600 acme.json.
Every configuration files here are stored in the “conf” folder. You can change the path to where you want, but remember to update your docker-compose file for it.
Content of the file
--- global: sendAnonymousUsage: false checkNewVersion: false api: dashboard: true pilot: dashboard: false log: filePath: "/etc/traefik/applog.log" format: json level: "ERROR" providers: docker: endpoint: unix:///var/run/docker.sock exposedByDefault: false watch: true swarmMode: false file: directory: "/dynamic" watch: true api: dashboard: true debug: false entryPoints: web: address: ":80" http: redirections: entryPoint: to: websecure scheme: https websecure: address: ":443" certificatesResolvers: letsencrypt: acme: email: firstname.lastname@example.org caServer: https://acme-staging-v02.api.letsencrypt.org/directory # caServer: https://acme-v02.api.letsencrypt.org/directory storage: "/etc/traefik/acme.json" keyType: EC256 httpChallenge: entryPoint: web
In this file, one important bloc is “provider” with the definition of a “dynamic” folder path. This folder is created locally to have the file “traefik_dynamic.yml”.
watch = true allows Traefik to watch changes in the configuration files and applies them when an update is done.
Certificates are generated with Let's Encrypt ; indeed, Traefik uses its internal tool “lego”. When you are in build mode, you should use “staging” server, which have a less aggressive limiter than the “acme-v02”. In production environment, use the “acme-v02” server from Let's Encrypt.
Dynamic configuration file is the same type as the main configuration file (YAML), difference is the settings. Here's my dynamic configuration file “traefik_dynamic.yml”, in the folder “conf/traefikdynamic” :
--- tls: options: default: minVersion: VersionTLS12 sniStrict: true cipherSuites: - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 - TLS_AES_128_GCM_SHA256 - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 curvePreferences: - CurveP521 - CurveP384 alpnProtocols: - h2 - http/1.1 mintls13: minVersion: VersionTLS13 http: middlewares: compression: compress: excludedContentTypes: - text/event-stream security: headers: accessControlAllowMethods: - GET - OPTIONS - PUT accessControlMaxAge: 100 addVaryHeader: true browserXssFilter: true contentTypeNosniff: true forceSTSHeader: true frameDeny: true stsPreload: true customFrameOptionsValue: SAMEORIGIN referrerPolicy: "origin-when-cross-origin" permissionsPolicy: "camera 'none'; microphone 'none'; geolocation 'none'; payment 'none';" stsSeconds: 315360000 hostsProxyHeaders: - "X-Forwarded-Host"
Some explanations :
- TLS block specify every needed options to have an optimal configuration. Minimal version of TLS is 1.2 with newer algorithms used by modern navigators ;
- HTTP bloc have 2 “under-blocs” :
- a middleware to compress some flux aside streaming
- a middleware for every security about HTTPS (headers)
Configuration files are ready, you now have to set up your services in the docker-compose.yml file. Here's what you need for every services behind Traefik :
labels: traefik.enable: "true" traefik.http.routers.service-https.entrypoints: "websecure" traefik.http.routers.service-https.middlewares: "security@file, compression@file" traefik.http.routers.service-https.tls: "true" traefik.http.routers.service-https.tls.certresolver: "letsencrypt"
compression@file are drawn in the file
When you set the docker labels, don't forget to re-up your containers (
docker-compose up -d).
If you don't use docker labels, you can add these blocs in the “traefikdynamic.yml” – information about “routers” and “services” next to the TLS configuration, in the bloc
http : (for example, I'm using Portainer)
services: sc-portainer: loadBalancer: servers: - url: "http://portainer:9000" routers: rt-portainer: entryPoints: - websecure middlewares: - security - compression service: sc-portainer rule: Host(`portainer.domain.local`) tls: certResolver: letsencrypt
You don't have to restart containers when you're done updates in the file “traefikdynamic.yml”. Updates (dynamic configuration) are taken when running.