Awesome
Traefik Setup with Docker Compose
This is a reusable Traefik config for usage on a virtual server or for local development using Docker Compose.
It uses:
- Traefik 3
- Docker
- Let's encrypt (Optional)
[!NOTE] Check out solidtime - The modern Open Source Time-Tracker at solidtime.io
Table of content
Production setup
Setting up traefik
- Clone repository
git clone https://github.com/korridor/reverse-proxy-docker-traefik.git cd reverse-proxy-docker-traefik
- Copy default config
cp docker-compose.prod.yml docker-compose.yml cp -r configs-prod configs echo "{}" > certificates/acme.json chmod 600 certificates/acme.json
- Replace domain for dashboard (
reverse-proxy.somedomain.com
inconfigs/dynamic/dashboard.yml
)http: routers: traefik: rule: Host(`reverse-proxy.somedomain.com`) # ... traefik-http-redirect: rule: Host(`reverse-proxy.somedomain.com`) # ...
- Replace password for admin account (in
configs/dynamic/dashboard.yml
)http: # ... middlewares: dashboardauth: basicAuth: users: - "user1:$2y$05$/x10KYbrHtswyR8POT.ny.H4fFd1n.0.IEiYiestWzE1QFkYIEI3m"
- You can use a website like this to generate the hash (use Bcrypt).
- Or generate it with:
echo $(htpasswd -nB user1)
- Replace email for Let's encrypt (
mail@somedomain.com
inconfigs/traefik.yml
)certificatesResolvers: letsencrypt: acme: # ... email: mail@somedomain.com
- Start container
docker compose up -d
- Check that Traefik is running smoothly
docker compose logs
Traefik dashboard
The Traefik dashboard is now available under:
https://reverse-proxy.somedomain.com
The dashboard shows you the configured routers, services, middleware, etc.
Connect docker compose service to reverse-proxy
version: '3.8'
networks:
frontend:
external: true
name: reverse-proxy-docker-traefik_routing
services:
someservice:
restart: always
# ...
labels:
- "traefik.enable=true"
- "traefik.docker.network=reverse-proxy-docker-traefik_routing"
# https
- "traefik.http.routers.someservice.rule=Host(`someservice.com`)"
- "traefik.http.routers.someservice.tls=true"
- "traefik.http.routers.someservice.tls.certresolver=letsencrypt"
- "traefik.http.routers.someservice.entrypoints=websecure"
# http (redirect to https)
- "traefik.http.routers.someservice-http.rule=Host(`someservice.com`)"
- "traefik.http.routers.someservice-http.entrypoints=web"
- "traefik.http.routers.someservice-http.middlewares=redirect-to-https@file"
networks:
- frontend
- ...
Password protection for service with basic auth
services:
someservice:
# ...
labels:
# ...
- "traefik.http.routers.someservice.middlewares=someservice-auth"
- "traefik.http.middlewares.someservice-auth.basicauth.users=user1:$2y$05$/x10KYbrHtswyR8POT.ny.H4fFd1n.0.IEiYiestWzE1QFkYIEI3m"
You can generate the escaped hash with the following command: echo $(htpasswd -nB user1) | sed -e s/\\$/\\$\\$/g
If you use a website like this to generate the hash remember to escape the dollar signs ($
-> $$
) and use Bcrypt.
Specifying port if service exposes multiple ports
If your service exposes multiple ports Traefik does not know which one it should use. With this line you can select one:
services:
someservice:
# ...
labels:
# ...
- "traefik.http.services.someservice.loadbalancer.server.port=8080"
SSL configuration
Per default the SSL configuration is set so that SSL Labs gives an A
rating.
If you want an A+
rating, you need to use HSTS (HTTP Strict Transport Security).
The setup includes a global middleware called hsts-minimal@file
that can be used to activate HSTS in a simple setting.
See "Global middlewares" for more information.
Global middlewares
hsts-minimal@file
Adds the HSTS header to the HTTP response without includeSubDomains
and preload
.
The max-age
is set to one year / 31536000 seconds.
hsts-standard@file
Adds the HSTS header to the HTTP response with includeSubDomains
and no preload
.
The max-age
is set to one year / 31536000 seconds.
hsts-full@file
Adds the HSTS header to the HTTP response with includeSubDomains
and preload
.
The max-age
is set to one year / 31536000 seconds.
redirect-to-https@file
Adds a permanent redirect to HTTPS.
redirect-non-www-to-www@file
Adds a permanent redirect (HTTP 301) from non-www domains to the HTTPS www domain Examples:
https://example.test
->https://www.example.test
http://example.test
->https://www.example.test
redirect-www-to-non-www@file
Adds a permanent redirect (HTTP 301) from www domains to the HTTPS non-www domain Examples:
https://www.example.test
->https://example.test
http://www.example.test
->https://example.test
Access Logs
To enable the Traefik access logs in the production configuration, open the file traefik.yml
within the config folder and uncomment the accessLog
section.
# Access logs
accessLog: {}
Setup for local development
Setting up Traefik
-
Clone repository
git clone https://github.com/korridor/reverse-proxy-docker-traefik.git cd reverse-proxy-docker-traefik
-
Copy default config
ln -s docker-compose.local.yml docker-compose.yml ln -s configs-local configs
If you want to change the configuration copy the configuration instead of creating a symlink.
cp docker-compose.local.yml docker-compose.yml cp -r configs-local configs
-
If you want you can change the domain of the traefik dashboard (
reverse-proxy.test
inconfigs/dynamic/dashboard.yml
)http: routers: traefik: rule: Host(`reverse-proxy.test`) # ...
-
Start container
docker compose up -d
-
Check that traefik is running smoothly
docker compose logs
Traefik dashboard
The Traefik dashboard is now available under:
http://reverse-proxy.test
The dashboard shows you the configured routers, services, middlewares, etc.
Connect docker compose service to reverse-proxy
version: '3.8'
networks:
frontend:
external: true
name: reverse-proxy-docker-traefik_routing
services:
someservice:
restart: always
# ...
labels:
- "traefik.enable=true"
- "traefik.docker.network=reverse-proxy-docker-traefik_routing"
# http
- "traefik.http.routers.someservice.rule=Host(`someservice.test`)"
- "traefik.http.routers.someservice.entrypoints=web"
networks:
- frontend
- ...
Enabling service to send requests to itself (with someservice.test)
services:
someservice:
# ...
extra_hosts:
- "someservice.test:10.100.100.10"
Specifying port if service exposes multiple ports
If your service exposes multiple ports Traefik does not know which one it should use. With this config line you can select one:
services:
someservice:
# ...
labels:
# ...
- "traefik.http.services.someservice.loadbalancer.server.port=8080"
Enable SSL locally
- Install mkcert
For example on macOS:
brew install mkcert
brew install nss # if you use Firefox
Now install the local CA:
mkcert -install
- Generate certificate
Replace someservice
with the domains that you are using for local development.
cd certificates
mkcert -key-file local.key.pem -cert-file local.cert.pem "*.local" "*.test" "*.someservice.test" "*.someservice.local"
Enable SSL in the docker compose file
version: '3.8'
networks:
frontend:
external: true
name: reverse-proxy-docker-traefik_routing
services:
someservice:
restart: always
# ...
labels:
- ...
# http
- ...
# https
- "traefik.http.routers.someservice-https.rule=Host(`someservice.test`)"
- "traefik.http.routers.someservice-https.entrypoints=websecure"
- "traefik.http.routers.someservice-https.tls=true"
networks:
- frontend
- ...
FAQ
I have a IPv6-only server, what do I need to change?
GitHub currently does not support cloning a repository over IPv6. You can clone from my Codeberg mirror instead:
git clone https://codeberg.org/korridor/reverse-proxy-docker-traefik.git
Credits
I used the following resources to create this setup:
- Traefik docs
- Traefik v2 and Mastodon, a wonderful couple! by Nicolas Inden
- GitHub repo traefik-example by jamct
License
This configuration is licensed under the MIT License (MIT). Please see license file for more information.