Intro
This is a part of series of posts about Traefik and its configuration.
More Recipes
We can use entities, defined via Docker labels, in multiple places. I will be taking advantage of this defining all possible middlewares in Traefik service. To allow that, one small adjustment is needed. We should include Traefik own service in label analysis:
traefik:
#...
labels:
traefik.enable: true
#...
Compression
Traefik, like any other reverse proxy, can compress proxied data. Use Compress middleware for this purpose.
Let's define a middleware by adding some labels to Traefik service:
traefik:
#...
labels:
#...
traefik.http.middlewares.compress-all.compress: true
#...
#...
And then, we can use it for Whoami service:
whoami:
#...
labels:
#...
traefik.http.routers.whoami.middlewares: compress-all
#...
#...
Re-deploy, hit F5 and...
The size. It matters. In this particular case at least.
Compress middleware has an option called minResponseBodyBytes
. It defines a minimum threshold for compression to kick in. Responses, smaller than this value won't be compressed. Default value is 1024
bytes which is slightly more than our response. Traefik just skipped it.

compression, or rather lack of it
To see middleware in action let's reduce minResponseBodyBytes
to 1 byte and see what happens:
traefik:
#...
labels:
#...
traefik.http.middlewares.gzip.compress.minresponsebodybytes: 1
#...
#...
Now, redeploy the stack and check again.

compression working, brotli in this case
Redirect, Remove WWW, Two Domains - same Service
Handling single domains like whoami.localhost is straightforward. Add whoami.localhost into your service's router rule, and be done.
Oftentimes it is required to deal with two domains:
- canonical like whoami.localhost;
- its CNAME, like www.whoami.localhost.
Required behavior all times the same:
- accepted request on www;
- redirect client to non-www;
- make sure it was a
301
redirect.
This can be achieved using redirectregex middleware.
Let's declare a middleware and some of its options:
traefik:
#...
labels:
#...
traefik.http.middlewares.wwwbegone.redirectregex.regex: '^https://www\.(.*)'
traefik.http.middlewares.wwwbegone.redirectregex.replacement: 'https://$${1}'
traefik.http.middlewares.wwwbegone.redirectregex.permanent: true
#...
#...
The options used:
regex
defines regex which will be used to match request URL;replacement
defines how to modify request URL;permanent
instructs Traefik to use 301 redirect instead of 302, which will be used by default.
And these are service labels.
whoami:
#...
labels:
#...
traefik.http.routers.whoami.rule: Host(`whoami.localhost`) || Host(`www.whoami.localhost`)
traefik.http.routers.whoami.middlewares: wwwbegone
#...
#...
Note highlighted line. There goes both domains, we need service answer on. More on this here.
Now redeploy the stack. Domain whoami.localhost should open as usual, but when you try to access www.whoami.localhost redirect will happen.

recieved 302 redirect

landed on non-www domain
Basic HTTP authentication
Another common thing is Basic HTTP Authentication. It can be implemented with basicauth middleware.
Defining middleware will be something like this:
traefik:
#...
labels:
#...
traefik.http.middlewares.keepthemaway.basicauth.users: "nmm2077:$$apr1$$q/wpkUkO$$3RLAT4KydMB1FteLOcIx90"
# traefik.http.middlewares.keepthemaway.basicauth.usersfile: "/path/to/my/usersfile"
#...
#...
You can only use users
or usersfile
option, but not both.
Value for users
setting consists of username, written in plain text, and a hashed password. MD5
, SHA1
, SHA256
, SHA512
or BCrypt
will do. If you want more than one user - write them one by one, delimiting pairs by a comma.
Password hashes can be obtained in various ways. My go to is to use openssl
:
openssl passwd -apr1
Password:
Verifying - Password:
$apr1$Jw/8DYLd$UEJTaPcqZCdpLGyMqn5Qr0
The string $apr1$Jw/8DYLd$UEJTaPcqZCdpLGyMqn5Qr0
is our password hash.
To use this middleware add it to service middleware list, as usual:
whoami:
#...
labels:
#...
traefik.http.routers.whoami.rule: Host(`whoami.localhost`)
traefik.http.routers.whoami.middlewares: keepthemaway
#...
#...
Let's see it in action.

password request dialogue, I already filled login and password in

firefox warns about potential security risk

request headers
If you decide to go with passwords in a file (usersfile
option) utility from apache2-utils
called httpasswd
can be used to generate required file.
# crezter file
htpasswd -c /path/to/.htpasswd username
# add another user
htpasswd /path/to/.htpasswd another_username
Each line of file will represent different user credentials. And you don't need to escape $
signs here. In our case content of .htpasswd
file will be:
nmm2077:$apr1$Jw/8DYLd$UEJTaPcqZCdpLGyMqn5Qr0
And only thing needs to be adjusted - is Traefik
service labels:
traefik:
#...
labels:
#...
# traefik.http.middlewares.keepthemaway.basicauth.users: "nmm2077:$$apr1$$q/wpkUkO$$3RLAT4KydMB1FteLOcIx90"
traefik.http.middlewares.myauth.basicauth.usersfile: /.htpasswd
#...
volumes:
#...
- ./.htpasswd:/.htpasswd
#...
#...
And that's it.
The End??
And this was it! For now, at least.
I'm pretty sure there's something more left in my notes, though.