🛡️ Traefik 2 - configuration TLS personnalisée
L'objectif de cet article est de configurer Traefik avec la meilleure configuration TLS personnalisée.
Version | Date | Commentaires |
---|---|---|
1 | 05/2022 | Création de l'article |
1.1 | 05/2023 | Mise à jour de la syntaxe, des numéros de version, ajout du contexte d'exécution |
1.2 | 07/2023 | Mise à jour des fichiers de configuration, ajout d'informations complémentaires dans les blocs "labels" et "configuration dynamique", correction des numéros de version, mise à jour des fichiers de configuration et des chemins |
Objectif : Configurer les options TLS de Traefik
Environnement : Debian 12
, Docker 24.x
, docker compose (plugin) 2.20.x
, Traefik 2.10
.
Contexte d'exécution :
- dossier oĂą se trouvent tous les fichiers et dossiers pour cet exemple :
/opt/docker/dc
- emplacement du fichier de configuration principal de Traefik :
/opt/docker/dc/conf/traefik.yml
- dossier oĂą se trouvent les configurations de Traefik (fichiers dynamiques) :
/opt/docker/dc/conf/traefikdynamic
- emplacement du fichier comportant tous les certificats générés par let's encrypt (ou autre) :
/opt/docker/dc/conf/acme.json
- dossier où se trouvent les journaux d'événements (logs) :
/opt/docker/dc/logs/
Configuration du fichier docker compose
Avant-propos, vous ne pouvez pas utiliser les deux types de configurations (statique et dynamique) en même temps, c'est l'un ou l'autre. Ici, je privilégie la configuration dynamique. Au besoin, vous trouverez un rappel des différents types de configuration à cette adresse.
Préparons notre fichier docker-compose.yml
:
---
services:
traefik:
image: traefik:saintmarcelin
container_name: traefik
restart: unless-stopped
ports:
- target : 80
published : 80
protocol: tcp
mode : host
### BEGIN dashboad
- target : 8080
published : 8080
protocol: tcp
mode : host
### END dashboard
- target : 443
published : 443
protocol: tcp
mode : host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./conf/traefikdynamic:/dynamic
- ./conf/traefik.yml:/etc/traefik/traefik.yml:ro
- ./conf/acme.json:/etc/traefik/acme.json
- ./logs/traefik.log:/etc/traefik/applog.log
environment:
TZ: Europe/Paris
Explications :
- J'utilise la version "saintmarcelin" de Traefik (v2.10.x).
- Exposition des ports TCP 80 et 443
- montage de plusieurs volumes : un premier fichier de configuration « traefik.yml » pour les options de base et le dossier entier pour les options dites « dynamiques ». Le dossier entier est monté, les fichiers à l'intérieur le seront donc aussi.
- Le fichier « acme.json » est à créer avant tout, via un
touch conf/acme.json && chmod 0600 conf/acme.json
.
Configuration de Traefik
Pour rappel, tous les fichiers de configuration que je vous propose sont créés dans un dossier « conf
». Libre à vous de placer les fichiers où vous le souhaitez, tant que vous modifiez correctement les chemins dans les configurations.
Contenu du fichier traefik.yml
:
---
global:
sendAnonymousUsage: false
checkNewVersion: false
api:
dashboard: true
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
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
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
Ce qui est important dans ce fichier, c'est le bloc "providers" avec la définition d'un dossier « dynamic ». Ce dossier est à créer en local auparavant sur votre machine pour y intégrer ensuite le fichier « dynamic.yml ».
La ligne watch: true
permet à Traefik de regarder les changements fourni dans les fichiers de configuration et de les appliquer une fois l'enregistrement du fichier effectué.
Les certificats sont générés à l'aide du service Let's Encrypt. En effet, Traefik, au travers de l'outil « Lego », ira lui-même générer les certificats nécessaires. Lors de vos tests, préférez utiliser le serveur "staging" qui a une limite plus haute que le serveur « acme-v02 ». Une fois les tests terminés, vous pouvez commenter la ligne "staging" et utiliser le serveur Let's Encrypt « acme-v02 ».
Le fichier de configuration secondaire (dynamique) est de même type que le « traefik.yml », la différence réside dans les paramètres. Pour rappel, le fichier « traefik.yml » contient la configuration pour le démarrage de Traefik, tandis que le fichier de configuration dynamique contient les options pour les middlewares, les routeurs et autres loadbalancers. Retrouvez ci-dessous mon fichier de configuration « dynamic.yml, dans le dossier « 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:
security:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlMaxAge: 100
addVaryHeader: true
browserXssFilter: true
contentTypeNosniff: true
customFrameOptionsValue: SAMEORIGIN
customResponseHeaders:
Access-Control-Allow-Origin: "*"
Sec-Fetch-Site: cross-site
X-Forwarded-Proto: https
forceSTSHeader: true
frameDeny: true
hostsProxyHeaders:
- "X-Forwarded-Host"
referrerPolicy: "strict-origin-when-cross-origin"
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
Quelques explications Ă fournir :
- Le bloc TLS instaure toutes les options nécessaires pour avoir une configuration optimale. Simplement, la version minimale est le TLS 1.2 avec des algorithmes de chiffrement utilisés par les navigateurs web modernes,
- le bloc « HTTP comporte deux sous-blocs :
- un premier middleware pour compresser certains flux sauf en cas de streaming
- un second middleware pour toutes les sécurités relative au HTTPS (les "headers" en-têtes).
Utilisation des labels docker
Pour que vos services sous docker soient exploités au travers de Traefik, vous avez deux possibilités : utiliser les labels docker, ou saisir une configuration dans les fichiers de Traefik. Pour cette partie, utilisons les labels.
Pour chaque service que vous souhaitez avoir derrière Traefik, ajoutez ces labels (à modifier en fonction du nom de vos entrypoints, vos noms de définition de middleware) :
Les middlewares security@file
et compression@file
viennent piocher directement les paramètres dans le fichier dynamic.yml
précédemment créé.
Lorsque vos labels sont mis en place, n'oubliez pas de relancer vos conteneurs Docker (docker-compose up -d
) et le tour est joué.
Ne pas utiliser les labels Docker et laisser Traefik chercher seul
Si vous ne souhaitez pas ou n'utilisez pas les labels docker, vous pouvez ajouter dans le fichier de configuration auparavant modifié des informations de « routeurs » et « services ». À la suite des configurations TLS, toujours dans la partie http
, deux nouveaux blocs doivent être ajoutés : (pour l'exemple, j'utiliserai le conteneur Portainer).
http:
...
services:
sc-portainer:
loadBalancer:
servers:
- url: "http://portainer:9000"
routers:
rt-portainer:
entryPoints:
- websecure
middlewares:
- security
service: sc-portainer
rule: Host(`portainer.domain.local`)
tls:
certResolver: letsencrypt
Le bloc « services » défini les conteneurs à accéder, en interne de votre infrastructure, avec le port de communication. Chaque service doit être défini pour être exploité au travers de Traefik, comme dans l'exemple ci-dessus.
Le bloc « routers » défini la route et les middlewares pour les services. Dans ce cas, je veux que le service « sc-portainer » utilise les deux middlewares, soit accessible via « portainer.domain.local » (ligne rule:
), et accessible en HTTPS depuis l'extérieur (certificat généré en utilisant le service letsencrypt
défini dans le fichier traefik.yml).
Cette configuration est plus pratique, car elle ne nécessite pas de changer le fichier docker-compose.yml de votre service. Traefik prend à chaud les modifications, dans les fichiers de configuration dynamique.