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
- 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
The Traefik dashboard is now available under:
https://reverse-proxy.somedomain.com
The dashboard shows you the configured routers, services, middleware, etc.
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"
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.
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
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: {}
-
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
The Traefik dashboard is now available under:
http://reverse-proxy.test
The dashboard shows you the configured routers, services, middlewares, etc.
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"
- 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"
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
- ...
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
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
This configuration is licensed under the MIT License (MIT). Please see license file for more information.