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