Traefik 2 Config
Tested against Traefik v.2.3.6
These are some default configurations I use for my Traefik 2 instances.
Configuration contains:
- Global HTTP redirect - supported from v2.2
- Secure Headers from dynamic_config.yml for HTTPS entrypoint
- API/Dashboard exposed via the dynamic_config.yml
- Let’s Encrypt HTTP Challenge certificates
- Docker and File Provider
- A+ SSL rating for all sites and the dashboard
- Add Tecnativa/docker-socket-proxy
Secure Headers and TLS options used are from https://ssl-config.mozilla.org so we get A+ SSL rating out-of-the-box
.env File for Docker compose
DOCKERDATADIR is for container persistent storage DOMAINNAME is for base DOMAIN for services exposed
DOCKERDATADIR=/data/containers
DOMAINNAME=example.org
Create Config/Data Files
Location for container data is the same as what is defined in the .env file above for DOCKERDATADIR
mkdir -p /data/containers/traefik2/{acme,config,log}
mkdir -p /data/docker
touch /data/docker/docker-compose.yml
touch /data/docker/.env
touch /data/containers/traefik2/config/traefik.yml
touch /data/containers/traefik2/config/dynamic_config.yml
touch /data/containers/traefik2/log/traefik.log
touch /data/containers/traefik2/acme/acme.json
chmod 600 /data/containers/traefik2/acme/acme.json
Docker-Compose
Location /data/docker/docker-compose.yml
version: "3.8"
networks:
proxy:
external: true
services:
#Traefik 2 Reverse Proxy
traefik:
image: traefik:v2.3 # Specified version due to watchtower auto-updating
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- $DOCKERDATADIR/traefik2/config/traefik.yml:/traefik.yml:ro
- $DOCKERDATADIR/traefik2/log/traefik.log:/traefik.log
- $DOCKERDATADIR/traefik2/acme:/etc/traefik/acme
- $DOCKERDATADIR/traefik2/config/dynamic_config.yml:/etc/traefik/dynamic_conf.yml:ro
labels:
#enable watchtower to keep Traefik updated automatically
- "com.centurylinklabs.watchtower.enable=true"
Traefik 2 Static Config
Location /data/containers/traefik2/config/traefik.yml
# Global configuration
#global:
# checkNewVersion: true
# sendAnonymousUsage: true
# EntryPoints configuration -v2.2 and higher for global redirect
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
https:
address: ":443"
http:
middlewares:
- secureHeaders@file
tls:
options: TLSv12@file
certResolver: le
# API and dashboard configuration
api:
dashboard: true
# Certificate Resolvers Configuration
certificatesResolvers:
le:
acme:
email: me@example.org
storage: /etc/traefik/acme/acme.json
httpChallenge:
entryPoint: http
# Logs
log:
filePath: traefik.log
# format: json
level: DEBUG
# Providers configuration
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /etc/traefik/dynamic_conf.yml
watch: true
Traefik 2 Dynamic Config
Location /data/containers/traefik2/config/dynamic_config.yml
-
If you’re using Global HTTP redirect and hosting some on the DOMAINNAME e.g. example.org you can use PathPrefix rule for the Dashboard with middleware to force the trailing slash
-
If there is no site directly on example.org HTTP redirect does not hit the dashboard rule, use subdomain then instead e.g.
rule: "Host(`traefik.example.org`)"
http:
routers:
dashboard:
entryPoints:
- https
rule: "Host(`example.org`) && (PathPrefix(`/api`) || PathPrefix(`/traefik`))"
service: api@internal # This is the defined name for api. You cannot change it.
middlewares:
- dashauth
- secureHeaders
- dashboard-stripprefix
tls:
options: TLSv12
certresolver: le
middlewares:
dashauth:
basicAuth:
users:
- "username:password"
# Dashboard strip prefix with forceSlash: true to force trailing slash on /Dashboard/
dashboard-stripprefix:
stripPrefix:
prefixes:
- "/traefik"
forceSlash: true
secureHeaders:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 315360000
referrerPolicy: "no-referrer"
customResponseHeaders:
Strict-Transport-Security: max-age=63072000
# Do not name 'default' it will not get applied when referenced: https://github.com/traefik/traefik/issues/6181
tls:
options:
TLSv13:
minVersion: VersionTLS13
cipherSuites:
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
TLSv12:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true