Skip to content

Traefik

Traefik is an open-source Application Proxy that automatically discovers and routes traffic to your services. It stands out for its native Docker integration and automatic service discovery capabilities, making it particularly powerful for container environments.

Preparation

Docker network

First, a Docker network should be created. This then eliminates the need to release ports for each individual service. Sufficient then are ports 80 and 443 for the proxy manager, as well as others in certain cases if necessary.

Terminal window
sudo docker network create proxy-network

Create directory

Terminal window
mkdir traefik
cd traefik
touch traefik.log
mkdir shared
mkdir acme
touch acme/acme.json
chmod 600 acme/acme.json
mkdir rules
touch rules/middlewares.toml
touch .env docker-compose.yml

Environment variables

Some environment variables are required to configure the Proxy Manager. A DNS challenge requires a domain from a supported provider.

You can get a .de domain from Netcup starting at €5/year(Affiliate-Link).

In this case you need the domain, your customer number, the API key and the API password.

Create a .env file with your DNS provider credentials:

.../traefik/.env
DOMAINNAME=domain.de
NETCUP_CUSTOMER_NUMBER=50000
NETCUP_API_KEY=LDBfH4MNyDlgBgww0lGry0OkouhkMqUI5E
NETCUP_API_PASSWORD=uEzCAzISBUBwGqW9oSEzRJuL3D26Gm1yQFMlnqSB1Lhjjb5Z98
EMAIL_ADDRESS=mail@hallo.de

Installation

Authentication

A username / password combination is required for authentication.

Terminal window
sudo apt install apache2-utils
htpasswd -nb benutzername passwort > /shared/.htpasswd

Afterwards the middleware has to be adjusted:

.../traefik/rules/middlewares.toml
[http.middlewares]
[http.middlewares.middlewares-basic-auth]
[http.middlewares.middlewares-basic-auth.basicAuth]
realm = "Traefik Basic Auth"
usersFile = "/shared/.htpasswd"

Docker Compose

The installation is done via Docker Compose.

.../traefik/docker-compose.yml
### NETWORKS ###
networks:
proxy-network:
external: true
### SERVICES ###
services:
traefik:
container_name: traefik
image: traefik:latest
restart: unless-stopped
command:
- --global.checkNewVersion=true
- --global.sendAnonymousUsage=false
- --entryPoints.http.address=:80
- --entryPoints.https.address=:443
- --entryPoints.traefik.address=:8080
- --api=true
- --api.dashboard=true
- --log=true
- --log.level=WARN
- --accessLog=true
- --accessLog.filepath=/traefik.log
- --accessLog.bufferingSize=100
- --accessLog.filters.statusCodes=400-499
- --providers.docker=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.exposedByDefault=false
- --providers.docker.network=web
- --providers.docker.swarmMode=false
- --providers.file.directory=/rules
- --providers.file.watch=true
- --certificatesResolvers.dns-netcup.acme.dnsChallenge.provider=netcup
# - --certificatesResolvers.dns-netcup.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
- --certificatesResolvers.dns-netcup.acme.email=$EMAIL_ADDRESS
- --certificatesResolvers.dns-netcup.acme.storage=/acme.json
- --certificatesResolvers.dns-netcup.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
- --certificatesResolvers.dns-netcup.acme.dnschallenge.delayBeforeCheck=300
networks:
- proxy-network
security_opt:
- no-new-privileges:true
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
- target: 8080
published: 8080
protocol: tcp
mode: host
volumes:
- ./rules:/rules
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme/acme.json:/acme.json
- ./traefik.log:/traefik.log
- ./shared:/shared
environment:
- NETCUP_CUSTOMER_NUMBER=$NETCUP_CUSTOMER_NUMBER
- NETCUP_API_KEY=$NETCUP_API_KEY
- NETCUP_API_PASSWORD=$NETCUP_API_PASSWORD
labels:
- "traefik.enable=true"
- "traefik.http.routers.http-catchall.entrypoints=http"
- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.traefik-rtr.entrypoints=https"
- "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)"
- "traefik.http.routers.traefik-rtr.tls=true"
- "traefik.http.routers.traefik-rtr.tls.certresolver=dns-netcup"
- "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME"
- "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
- "traefik.http.routers.traefik-rtr.service=api@internal"
- "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file"
Terminal window
sudo docker compose up -d

It may take a few minutes for traefik to load. Especially the DNS challenge can take a lot of time. Afterwards, the dashboard should be accessible under traefik.domain.de.

Other services

Another application can be connected to traefik via labels.

Terminal window
mkdir homepage
cd homepage
mkdir html
touch html/index.html
touch docker-compose.yml
.../homepage/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Homepage</title>
</head>
<body>
<h1>Homepage</h1>
<p>This is a homepage.</p>
</body>
</html>
.../homepage/docker-compose.yml
networks:
proxy-network:
external: true
### SERVICE ###
services:
homepage:
container_name: homepage
image: nginx:latest
restart: unless-stopped
networks:
- proxy-network
security_opt:
- no-new-privileges:true
volumes:
- /html:/usr/share/nginx/html:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.testseite-rtr.entrypoints=https"
- "traefik.http.routers.testseite-rtr.rule=Host(`homepage.$DOMAINNAME`)"
- "traefik.http.routers.testseite-rtr.tls=true"
- "traefik.http.routers.testseite-rtr.service=testseite-svc"
- "traefik.http.services.testseite-svc.loadbalancer.server.port=80"
Terminal window
sudo docker compose up -d

The page should now be accessible under homepage.domain.de.

Update

Keep Traefik up to date using Docker Compose:

Terminal window
sudo docker compose pull
sudo docker compose down
sudo docker compose up -d