Dynamic configurations
Now on to the dynamic configurations in /srv/traefik/traefik.d/
, where we define our operations!
In this section, I’m going to cover the following:
Administrators
To see how this is used to restrict access to specific users as a part of multiple middlewares being applied, please see the Traefik dashboard section.
/srv/traefik/traefik.d/core-admins.toml
[http.middlewares]
[http.middlewares.admin-users.basicAuth]
usersFile = "/users/admins"
/srv/traefik/traefik.d/core-admins.yaml
http:
middlewares:
admin-users:
basicAuth:
usersFile: "/users/admins"
Bastion hosts
To see how this is used to restrict access to specific hosts as a part of multiple middlewares being applied, please see the Traefik dashboard section.
/srv/traefik/traefik.d/core-bastions.toml
[http.middlewares]
[http.middlewares.bastion-hosts.ipWhiteList]
sourceRange = [
"1.1.1.1", # Admin Server #1
"2.2.2.2", # Admin Server #2
"3.3.3.3", # VPN
]
/srv/traefik/traefik.d/core-bastions.yaml
http:
middlewares:
bastion-hosts:
ipWhiteList:
sourceRange:
- "1.1.1.1", # Admin Server #1
- "2.2.2.2", # Admin Server #2
- "3.3.3.3", # VPN
Certificates
To see how these certificates are easily generated (and renewed) and distributed to Traefik instances on a routine schedule, please check out my prior article, Simple certs with Docker-Dehydrated.
If you’re familiar with the concept of SNI (Server Name Indication), Traefik matches hostnames to loaded certificates. Did you just register a domain and generate a new certificate that’s been copied to your Traefik server? Add it into this file, save the changes, and Traefik will pick up on it without needing to be restarted — the same goes for when a certificate is renewed and synchronized to a Traefik server.
/srv/traefik/traefik.d/core-certificates.toml
[tls.options]
[tls.options.default]
sniStrict = true
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
]
[[tls.certificates]]
certFile = "/letsencrypt/thad.getterman.org/fullchain.pem"
keyFile = "/letsencrypt/thad.getterman.org/privkey.pem"
[[tls.certificates]]
certFile = "/letsencrypt/ltg.fyi/fullchain.pem"
keyFile = "/letsencrypt/ltg.fyi/privkey.pem"
/srv/traefik/traefik.d/core-certificates.yaml
tls:
options:
default:
sniStrict: true
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
certificates:
- certFile: /letsencrypt/thad.getterman.org/fullchain.pem
keyFile: /letsencrypt/thad.getterman.org/privkey.pem
- certFile: /letsencrypt/ltg.fyi/fullchain.pem
keyFile: /letsencrypt/ltg.fyi/privkey.pem
Redirect traffic with regex patterns
I prioritize the following rule (the higher the number, the higher the priority) and strip the www
sub-domain from my URL shortener domain with the following:
/srv/traefik/traefik.d/route-ltg.fyi.toml
# Remove WWW
[http.routers.Router-YOURLS-WWW]
entrypoints = ["websecure"]
rule = "Host(`www.ltg.fyi`)"
priority = 90
service = "nginx"
middlewares = [
"YOURLS-Redirect-RemoveWWW",
]
[http.routers.Router-YOURLS-Loader.tls]
# Middlewares
[http.middlewares]
# Remove WWW
[http.middlewares.YOURLS-Redirect-RemoveWWW.redirectRegex]
regex = "^https://www.ltg.fyi/(.*)"
replacement = "https://ltg.fyi/${1}"
/srv/traefik/traefik.d/route-ltg.fyi.yaml
# Remove WWW
http:
routers:
Router-YOURLS-WWW:
entryPoints:
- "websecure"
rule: "Host(`www.ltg.fyi`)"
priority: 90
service: nginx
middlewares:
- YOURLS-Redirect-RemoveWWW
tls: {}
# Middlewares
http:
middlewares:
YOURLS-Redirect-RemoveWWW:
redirectRegex:
regex: "^https://www.ltg.fyi/(.*)"
replacement: "https://ltg.fyi/${1}"
Block sensitive paths
I use this middleware plug-in extensively, which I define with:
/srv/traefik/traefik.d/block-sensitive.toml
[http.middlewares]
[http.middlewares.block-sensitive.plugin.blockpath]
regex = [
"^/.svn",
"^/.git",
"^/.ht",
"^/.user.ini",
]
/srv/traefik/traefik.d/block-sensitive.yaml
http:
middlewares:
block-sensitive:
plugin:
blockpath:
regex:
- "^/.svn"
- "^/.git"
- "^/.ht"
- "^/.user.ini"
Then, I enable this for my sites, such as for LTG.FYI:
/srv/traefik/traefik.d/route-ltg.fyi.toml
[http.routers.Router-YOURLS-Loader]
entrypoints = ["websecure"]
rule = "Host(`ltg.fyi`) && Method(`GET`) && Path(`/{[a-zA-Z0-9]+}`)"
service = "nginx"
middlewares = [
"block-sensitive",
]
[http.routers.Router-YOURLS-Loader.tls]
/srv/traefik/traefik.d/route-ltg.fyi.yaml
http:
routers:
Router-YOURLS-Loader:
entryPoints:
- "websecure"
rule: "Host(`ltg.fyi`) && Method(`GET`) && Path(`/{[a-zA-Z0-9]+}`)"
service: nginx
middlewares:
- block-sensitive
tls: {}
Services
Nginx
As you just saw with an excerpt from the configuration for LTG.FYI, I call on the service nginx
. With multiple sites using the same service, I need only define that service once:
/srv/traefik/traefik.d/service-nginx.toml
[http.services]
[http.services.nginx.loadBalancer]
[[http.services.nginx.loadBalancer.servers]]
url = "http://nginx:80"
/srv/traefik/traefik.d/service-nginx.yaml
http:
services:
nginx:
loadBalancer:
servers:
- url: "http://nginx:80"
Who am I?
Traefik Labs has made a simple Docker image that displays information about HTTP requests sent to it. I frequently use this when I’m setting up a new route, or want to test middleware before deploying it. Similar to Nginx, I define the service once to be called by my routes:
/srv/traefik/traefik.d/service-whoami.toml
[http.services]
[http.services.whoami.loadBalancer]
[[http.services.whoami.loadBalancer.servers]]
url = "http://whoami:80"
/srv/traefik/traefik.d/service-whoami.yaml
http:
services:
whoami:
loadBalancer:
servers:
- url: "http://whoami:80"
Example.com
Occasionally, I need to pass a request to a remote site that’s been secured with HTTPS. The easiest way for me to see if it works is to send it to example.com.
/srv/traefik/traefik.d/service-example.toml
[http.services]
[http.services.example.loadBalancer]
passHostHeader = false
[[http.services.example.loadBalancer.servers]]
url = "https://example.com/"
/srv/traefik/traefik.d/service-example.yaml
http:
services:
example:
loadBalancer:
passHostHeader: false
servers:
- url: "https://example.com/"
Traefik dashboard
This is a bit of an exotic setup:
- 2 domains (Thad.Getterman.org and LTG.FYI), 1 path (
/traefik
). - Restricted access
- Bastion hosts
- Administrative users
- Fooling the dashboard into thinking that it’s sitting on its own domain — and why you see so many people typically use Traefik as a sub-domain such as
traefik.example.com
.- Stripping
/traefik
from the path that’s passed to the Traefik dashboard. - Replacing all occurrences of
/api
with/traefik/api
.
- Stripping
/srv/traefik/traefik.d/route-traefik-dashboard.toml
[http.routers.Router-Dashboard]
entrypoints = ["websecure"]
rule = "(Host(`thad.getterman.org`) || Host(`ltg.fyi`)) && PathPrefix(`/traefik`)"
service = "api@internal"
middlewares = [
"bastion-hosts",
"admin-users",
"dashboard-stripprefix",
"rewrite-dashboard-api",
]
[http.routers.Router-Dashboard.tls]
[http.middlewares]
# Don't pass /traefik to the service.
[http.middlewares.dashboard-stripprefix.stripPrefix]
prefixes = ["/traefik"]
[http.middlewares.rewrite-dashboard-api.plugin.rewritebody]
# Keep Last-Modified header returned by the HTTP service.
# By default, the Last-Modified header is removed.
lastModified = true
# Rewrites all "/api" occurences with "/traefik/api".
[[http.middlewares.rewrite-dashboard-api.plugin.rewritebody.rewrites]]
regex = "/api"
replacement = "/traefik/api"
/srv/traefik/traefik.d/route-traefik-dashboard.yaml
http:
routers:
Router-Dashboard:
entryPoints:
- "websecure"
rule: "(Host(`thad.getterman.org`) || Host(`ltg.fyi`)) && PathPrefix(`/traefik`)"
service: "api@internal"
middlewares:
- bastion-hosts
- admin-users
- dashboard-stripprefix
- rewrite-dashboard-api
tls: {}
middlewares:
# Don't pass /traefik to the service.
dashboard-stripprefix:
stripPrefix:
prefixes:
- "/traefik"
rewrite-dashboard-api:
plugin:
rewritebody:
# Keep Last-Modified header returned by the HTTP service.
# By default, the Last-Modified header is removed.
lastModified: true
# Rewrites all "/api" occurences with "/traefik/api".
rewrites:
regex: "/api"
replacement: "/traefik/api"
Table of Contents
One reply on “Traefik 2.5 quick-start guide”
Great article. Will definitely try out the local plugins