Skip to main content

Traefik v2 Webproxy Configuration - 1st Attempt

Central, Hong Kong

This guide is incomplete... Traefik, atm unfortunately, does not match my workflow. I am running into a lot of issues with the official documentation as well as the countless tutorials out there. I will put this project on hold until I figured it out.

So far I have been primarily working with NGINX. But diving into Kubernetes and Hashicorp Consul the name Traefik kept coming up. So let's have a look what this is all about.

Preparation

Folders and Files

mkdir -p /opt/traefik/{certs,shared,rules}
touch /opt/traefik/traefik.log

Proxy Network

docker network create --gateway 192.168.144.1 --subnet 192.168.144.0/24 traefik_proxy

Docker Compose

Create a docker-compose.yml file where you will define a reverse-proxy service that uses the official Traefik image:

version: '3'

networks:
traefik_proxy:
external:
name: traefik_proxy
default:
driver: bridge

services:
reverse-proxy:
container_name: traefik
restart: unless-stopped
# The official v2 Traefik docker image
image: traefik:v2.5
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- '8080:80'
# The Web UI (enabled by --api.insecure=true)
- '8081:8080'
networks:
traefik_proxy:
ipv4_address: 192.168.144.254
command: # CLI arguments
- --log=true
- --log.level=DEBUG # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
- --accessLog=true
- --accessLog.filePath=/traefik.log
- --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
- --accessLog.filters.statusCodes=400-499
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.log:/traefik.log
docker-compose up -d reverse-proxy

Check the API with jq (apt-get install jq):

curl http://localhost:8081/api/rawdata | jq

Traefik Detects New Services and Creates the Route for you. Add a web service to the docker-compose file and label it so it is picked up by Traefik:

whoami:
# A container that exposes an API to show its IP address
image: traefik/whoami
networks:
- traefik_proxy
labels:
- 'traefik.http.routers.whoami.rule=Host(`whoami.localhost`)'
docker-compose up -d whoami

The API now shows us that the Whoami Service is up and running;

curl http://localhost:8081/api/rawdata | jq

"whoami@docker": {
"entryPoints": [
"http"
],
"service": "whoami-traefik",
"rule": "Host(`whoami.localhost`)",
"status": "enabled",
"using": [
"http"
]
}
curl -H Host:whoami.localhost http://127.0.0.1:8080

Hostname: 49323f79f37b
IP: 127.0.0.1
IP: 192.168.144.101
RemoteAddr: 192.168.144.254:42418
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.74.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.144.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 3a33e661f746
X-Real-Ip: 192.168.144.1

Traefik Load Balancing

Run more instances of your whoami service with the following command:

docker-compose up -d --scale whoami=2

We can now send two request and will get the replies from both instances in a RR fashion:

curl -H Host:whoami.localhost http://127.0.0.1:8080

Hostname: 51ba8be4f4ec
IP: 127.0.0.1
IP: 192.168.144.2


curl -H Host:whoami.localhost http://127.0.0.1:8080

Hostname: 749f615cab45
IP: 127.0.0.1
IP: 192.168.144.3

Basic Authentication

Logins in Docker-Compose File

services:
reverse-proxy:
container_name: traefik
restart: unless-stopped
image: traefik:v2.5
ports:
- '8080:80'
- '8081:8080'
networks:
traefik_proxy:
ipv4_address: 192.168.144.254
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.log:/traefik.log
command: # CLI arguments
- '--api.insecure=true' # Traefik 2 dashboard authentication
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=false'
- '--providers.docker.network=default'
- '--entrypoints.web.address=:80'
- '--api'
- '--log=true'
- '--log.level=DEBUG' # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
- '--accessLog=true'
- '--accessLog.filePath=/traefik.log'
- '--accessLog.bufferingSize=100' # Configuring a buffer of 100 lines
- '--accessLog.filters.statusCodes=400-499'
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)'
- 'traefik.http.routers.http-catchall.entrypoints=web'
# auth middleware with "test:test" or "test2:test2"
- 'traefik.http.middlewares.my-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0'

whoami:
image: traefik/whoami
networks:
- traefik_proxy
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.whoami.rule=Host(`whoami.localhost`)'
- 'traefik.http.routers.whoami.entrypoints=web'
# connect your auth middleware to a service which you want to protect
- 'traefik.http.routers.whoami.middlewares=my-auth'

Test your configuration - accessing your service now requires a login:

curl -H Host:whoami.localhost http://127.0.0.1:8080
401 Unauthorized
curl -u test -H Host:whoami.localhost http://127.0.0.1:8080

Enter host password for user 'test':
Hostname: 8e1edc591948
IP: 127.0.0.1
IP: 192.168.144.2
RemoteAddr: 192.168.144.254:51444
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.74.0
Accept: */*
Accept-Encoding: gzip
Authorization: Basic dGVzdDp0ZXN0
X-Forwarded-For: 192.168.144.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: a037bf49a135
X-Real-Ip: 192.168.144.1

External Password File

The usersFile option is the path to an external file that contains the authorized users for the middleware. Start by creating a .htpasswd file with the login credentials:

apt-get install apache2-utils
htpasswd -c /opt/traefik/shared/.htpasswd myuser

We now need to mount both our rule and the password file into the Traefik Docker container and make sure that Traefik actually uses these files:

services:
reverse-proxy:
container_name: traefik
restart: unless-stopped
image: traefik:v2.5
ports:
- '8080:80'
- '8081:8080'
networks:
traefik_proxy:
ipv4_address: 192.168.144.254
volumes:
- /opt/traefik/rules:/rules
- /opt/traefik/shared:/shared
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.log:/traefik.log
command: # CLI arguments
- '--api.insecure=false' # Traefik 2 dashboard authentication
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=true'
- '--providers.docker.network=default'
- '--entrypoints.web.address=:80'
- '--api'
- '--log=true'
- '--log.level=ERROR' # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
- '--accessLog=true'
- '--accessLog.filePath=/traefik.log'
- '--accessLog.bufferingSize=100' # Configuring a buffer of 100 lines
- '--accessLog.filters.statusCodes=400-499'
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)'
- 'traefik.http.routers.http-catchall.entrypoints=web'
# auth middleware with path to .htpasswd as mounted in volumes
- 'traefik.http.middlewares.my-auth.basicauth.usersfile=/shared/.htpasswd'

whoami:
image: traefik/whoami
networks:
- traefik_proxy
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.whoami.rule=Host(`whoami.localhost`)'
- 'traefik.http.routers.whoami.entrypoints=web'
# connect your auth middleware to a service which you want to protect
- 'traefik.http.routers.whoami.middlewares=my-auth'
curl -H Host:whoami.localhost http://127.0.0.1:8080
401 Unauthorized
curl -u myuser -H Host:whoami.localhost http://127.0.0.1:8080

Enter host password for user 'myuser':
Hostname: 8658cc0f5b2a
IP: 127.0.0.1
IP: 192.168.144.2
RemoteAddr: 192.168.144.254:54796
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.74.0
Accept: */*
Accept-Encoding: gzip
Authorization: Basic
X-Forwarded-For: 192.168.144.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: c5f9a76e16e6
X-Real-Ip: 192.168.144.1