Setup Traefik
19-01-2024
Do you use docker? Do you use nginx or apachi to proxy the container? Fear not you won’t be needing them anymore once you are done with this tutorial.
Traefik is a simple docker centric proxy manager that is amazing and allows you to easilly proxy you docker containers with just a couple of labels.
Setting up Traefik
In this part we will setup traefik, with the dashboard enabled and secured with https and a password.
Create a directory where you will keep traefik configuration files and the docker compose. Inside it we will save all the configuration files.
docker-compose.yml
version: '3'
services:
traefik:
image: traefik:v2.5
container_name: traefik
ports:
- 80:80
- 443:443
volumes:
- ./traefik.toml:/traefik.toml
- ./traefik_dynamic.toml:/traefik_dynamic.toml
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
networks:
- web
labels:
- traefik.enable=false
restart: unless-stopped
networks:
web:
external: true
What we are doing here is binding the needed configuration files, the docker socket so traefik can listen to it and automatically proxy the services, and the acme.json which will keep our ssl certificates.
We are also forcing it to use the latest available stable image to make sure there are no bugs, and disabling proxying the traefik image itself io the lables to make sure it isn’t exposed by any means.
We are also making it so it can restart itself unless we specifically stop it, and binding it to port 80 and 443 because those are the default http and https ports that every browser uses when connecting.
traefik.toml
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[api]
dashboard = true
insecure = false
[certificatesResolvers.lets-encrypt.acme]
email = "name@domain.tld"
storage = "acme.json"
[certificatesResolvers.lets-encrypt.acme.tlsChallenge]
[providers.docker]
watch = true
network = "web"
[providers.file]
filename = "traefik_dynamic.toml"
watch = true
In the entryPoints we are defining the http and https ports and forcing http to redirect to https.
In the api section we are enabling the dashboard, but disallowing insecure access to it.
In the rest of the config we are defining the mail and storage for tls certificates, and enabled docker provider binded to a web network, and enabled the file provider for the dashboard setup.
traefik_dynamic.toml
[http.middlewares.simpleAuth.basicAuth]
users = [
"somebody:$apr1$whatever"
]
[http.routers.api]
rule = "Host(`monitor.domain.tld`)"
entrypoints = ["websecure"]
middlewares = ["simpleAuth"]
service = "api@internal"
[http.routers.api.tls]
certResolver = "lets-encrypt"
Here we are defining the basic auth credentials and routing the monitor domain to the dashboard with basic auth credentials and https.
Make sure to subsitute the string in qutes for users with what you get generated with httpasswd command: htpasswd -n somebody
.
acme.toml
To create acme.toml
run this command touch acme.toml && chmod 600 acme.toml
and we are done.
docker web network
You might have seen the networks part in the docker compose, we need to create it to make other docker containers in different docker compose files be accessible to traefik so it can proxy to them.
To create it we just need to run docker network create web
and we are done.
After all this is done, we can just run docker compose up -d
and if everyting was setup correctly, running docker compose logs -f
shouldn’t show any errors.
Using trafik to proxy to docker containers
Now I’m going to explain to you how to use traefik to proxy to docker containers by using labels. For that I will be using ntfy docker image as an example.
docker-compose.yml
version: "2.3"
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
command:
- serve
volumes:
- ./cache:/var/cache/ntfy
- ./ntfy:/etc/ntfy
- ./users:/var/lib/ntfy
healthcheck:
test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
networks:
- web
labels:
- traefik.http.routers.ntfy.rule=Host(`ntfy.domain.tld`)
- traefik.http.routers.ntfy.tls=true
- traefik.http.routers.ntfy.entrypoints=websecure
- traefik.http.routers.ntfy.tls.certresolver=lets-encrypt
- traefik.port=80
networks:
web:
external: true
The important part’s of this docker compose are the following:
-
No exposing ports
As you can see, with traefik you don’t need to expose port’s from the container making it a lot more secure as it can directly proxy to them from itself using the web network.
-
labels
In labels we are defining the host domain we wan’t to proxy to our container, we are also enabled tls and with entrypoints making the container only acessible from https, making it impossible to be accessible with http no matter what.
We are also defining the certresolver to be lets-encrypt and setting the port from the container that traefik needs to proxy to 80, this port can be different depending on what you want to proxy.
-
networks
We are also defining the web external network that is ussed so traefik can access to the container and proxy to it.
After you have accustomed the config to what you need, you can just docker compose up -d
, go to your traefik monitor and after some time you will see ntfy addedd to reverse proxying with tls certficate and only accessible from https.
Disabling traefik
Next I will be talkling about how to disable traefik for containers because you don’t want it to work for containers you dont want accessible over the network.
Disabling for one service docker-compose
As the main example, I have a watchtower instance that I dont wan’t proxied to the outside world. To do that we just add traefik.enable=false
to the labels and trafik will stop being naughty.
example
...
labels:
- traefik.enable=false
...
Take note that for this kind of docker-compose files, networks part IS NOT NEEDED, just create the docker compose file as you would usually without having the networks part.
Disabling for more complex docker-compose
Now here comes the more tricky part, disabling it for only specific docker containers, and making it so traefik cant access them from its network. To accomplish that we will use the traefik.enable=false
label once again, and make use of multiple networks to make sure traefik can only access the web interfaces and keep other containers secure like databases and only accessible to the web interfaces.
example docker-compose.yml
version: "3"
networks:
web:
external: true
internal:
external: false
services:
blog:
image: wordpress:4.9.8-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.http.routers.blog.rule=Host(`blog.domain.tld`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=lets-encrypt
- traefik.port=80
networks:
- internal
- web
depends_on:
- mysql
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
adminer:
image: adminer:4.6.3-standalone
labels:
labels:
- traefik.http.routers.adminer.rule=Host(`db-admin.domain.tld`)
- traefik.http.routers.adminer.tls=true
- traefik.http.routers.adminer.tls.certresolver=lets-encrypt
- traefik.port=8080
networks:
- internal
- web
depends_on:
- mysql
Here we can see what I was talking about in action, take note I took this docker compose file from this digital ocean blog post that explains it a lot better I could which you can use as a reference if you didnt understand something about what I was talking about.
Conclusing
I hope that you were able to setup traefik, or if not and were just reading to see what its all about I hope you had a good read and might have decided to try out traefik in the future.