Traefik
Traefik Doc: https://doc.traefik.io/traefik/routing/providers/docker/
Config acme.json - Setup
docker network create zabra # will be used by traefik and all containers behind it
touch acme.json
chmod 600 acme.json
touch /var/log/traefik-access.log
# Create user/password for traefik GUI basic authentification
# And store the value in variable CREDS=myser:$$xyxxx in .env file
# Sed command is used to double all $ for escaping
echo $(htpasswd -nB $USER) | sed -e s/\\$/\\$\\$/g
Traefik V3
Create traefik.yaml
Create traefik.yaml file with Let's Encrypt as certificate resolver and TLS Cipher settings
traefik.yaml
api:
dashboard: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
accessLog:
filePath: "/var/log/access.log"
format: json
certificatesResolvers:
letsencrypt:
acme:
email: "email.to.kone@gmail.com"
storage: "acme.json"
httpChallenge:
entryPoint: web
http:
middlewares:
# Basic Auth
auth:
basicAuth:
users:
- ${CREDS}
# HSTS / Security headers
servicests:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
isDevelopment: false
tls:
options:
default:
sniStrict: true
curvePreferences:
- CurveP521
- CurveP384
minVersion: TLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
mintls13:
minVersion: TLS13
providers:
file:
directory: /etc/traefik/dynamic
docker:
watch: true
exposedByDefault: false
network: zabra
Docker Compose FIle
docker-compose.yml
networks:
zabra:
external: true
services:
traefik:
image: "traefik:v3.5.3"
container_name: "traefik"
hostname: "traefik.enoks.fr"
restart: always
networks:
- zabra
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.api.rule=Host(`traefik.enoks.fr`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.routers.api.middlewares=auth,servicests"
# Basic Auth
- "traefik.http.middlewares.auth.basicAuth.users=${CREDS}"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yaml:/etc/traefik/traefik.yaml
- ./dynamic:/etc/traefik/dynamic:ro
- ./acme.json:/acme.json
- /var/log/traefik-access.log:/var/log/access.log
# mount custom CA
# - ./ca.crt:/etc/traefik/ssl/ca.crt:ro
Then run docker compose up -d
Enabling mTLS
dynamic/mtls.yaml
tls:
options:
mtls-required:
clientAuth:
caFiles:
- /etc/traefik/ssl/ca.crt # mount this in Traefik container
clientAuthType: RequireAndVerifyClientCert
minVersion: TLS12
sniStrict: true
Then the client app can add this addtionnal label - "traefik.http.routers.<ROUTER>.tls.options=mtls-required@file" to enforce Certificate Based Authentication.
Any user or device must present a certificate signed by the ca.crt to get access
Traefik V2 - OLD
Create
traefik.tomlfile with Let's Encrypt as certificate resolver.
traefik.toml
[api]
dashboard = true
# insecure = true ## using https
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http]
[entryPoints.web.http.redirections]
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
permanent = true
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http.tls]
certResolver = "default"
[accessLog]
filePath = "/var/log/access.log"
format = "json"
[http.middlewares]
[http.middlewares.test-auth.basicAuth]
usersFile = "/usersfile"
[providers]
[providers.docker]
watch = true
exposedByDefault = false
network = "zabra"
[providers.file]
filename = "/etc/traefik/tls_config.toml" # For TLS Hardening
[certificatesResolvers.letsencrypt.acme]
email = "user@email"
storage = "acme.json"
[certificatesResolvers.letsencrypt.acme.httpChallenge]
# used during the challenge
entryPoint = "web"
TLS Hardening
Traefik TLS Hardening to not support TLS 1.0, TLS 1.1 and enforce some ciphers.
tls_config.toml
# https://doc.traefik.io/traefik/https/tls/
# check results : nmap -Pn --script ssl-enum-ciphers -p 443 doc.enoks.fr or https://www.ssllabs.com/ssltest/analyze.html
[tls.options]
[tls.options.default]
sniStrict = true
curvePreferences = ["CurveP521", "CurveP384"]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
]
[tls.options.mintls13]
minVersion = "VersionTLS13"
docker-compose.yml with the tls config
# Adapt traefik_url
version: "3.3"
networks:
zabra:
external: true
services:
traefik:
image: "traefik:v2.9"
container_name: "traefik"
hostname: "traefik"
restart: always
networks:
- zabra
labels:
# dashboard access without port 8080
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`traefik_url`)"
- "traefik.http.routers.api.service=api@internal"
# https
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
# auth
- "traefik.http.routers.api.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=${CREDS}"
# Enforce HSTS (HTTP Strict Transport Security) & STS Headers for the UI.
- "traefik.http.middlewares.servicests.headers.stsseconds=31536000"
- "traefik.http.middlewares.servicests.headers.stspreload=true"
- "traefik.http.middlewares.servicests.headers.stsincludesubdomains=true"
- "traefik.http.middlewares.servicests.headers.isdevelopment=false"
# Disable STS service for traefik dashboard as it prevents basic HTTP authentification to work
# Need to check if there is an option to enable the both to work as the same time
# - "traefik.http.routers.api.middlewares=servicests"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.toml:/etc/traefik/traefik.toml
# Mount TLS config
- ./tls_config.toml:/etc/traefik/tls_config.toml
- ./acme.json:/acme.json
- /var/log/traefik-access.log:/var/log/access.log