Try to understand what is traefik and Try to use its forward auth module

The official website 

https://doc.traefik.io/traefik/

Trust me, you would learn nothing from there.

Clear Responsibilities

  • Providers is the ‘config file’ for traefik, it can be defined in a single file called traefik_dynamic_config.yaml or it can get defined inside of docker-compose labels section

  • Entrypoints listen for incoming traffic (ports, http(web), https(websecure))

  • Routers defines the rules to forward different requests to different services (by host-domain, URL path, headers and so on…)

  • Middlewares is in the middle of router and service, it can be used to modify the request URL, headers, or simply drop the request based on some condition (header authentication, rate limiting, and so on…)

  • Services defines the service URL, http://** or h2c://** (you could also define load balancing here)

Still in struggling? Watch the video below.

Video Tutorial

https://www.youtube.com/watch?v=Gk9WER6DunE&ab_channel=AFKDeveloper

Let’s see if we can understand its forward auth example (I wrote it)

#docker-compose.yml
version: "3.9"

services:
  traefik:
    image: "traefik:v2.9.6"
    restart: unless-stopped
    container_name: traefik
    ports:
      - "80:80" # <== http
      - "443:443" # <== https
      - "8080:8080" # <== :8080 is where the dashboard(config info table) runs on
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true" # <== Set to false in PRODUCTION!
      - "--providers.file.directory=/traefik_dynamic_configs" # <== config_folder
      - "--providers.file.watch=true" # <== when you change config yaml file, it will do a reload automaticlly
      - "--providers.docker=true" # <== also use docker-compose's label config
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"

    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik_dynamic_configs:/traefik_dynamic_configs" # <== Volume for dynamic conf file

  whoami:
    image: "traefik/whoami"
    expose: #expose port to other container by using http://whoami:80
      - "80"

    labels:
    - "traefik.enable=true" # <== Enable traefik to proxy this container
    - "traefik.http.routers.whoami_config.rule=Host(`whoami.yingshaoxo.xyz`)" # <== Your Sub Domain Name

    # - "traefik.http.routers.whoami_config.rule=PathPrefix(`/auth`)" # an alternative, may be yingshaoxo.xyz/auth
    # - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/auth" # define a middleware
    # - "traefik.http.routers.whoami_config.middlewares=test-stripprefix" # <== use that middleware

    - "traefik.http.middlewares.whatevername.forwardauth.address=http://host.docker.internal:1110/auth" # <== This defines a middleware for the auth, it was written by python
    - "traefik.http.routers.whoami_config.middlewares=whatevername" # <== Use the middleware defined above. If you want to use two middleware, use ',' to separate them, like 'middleware1, middleware2'

    - "traefik.http.services.whoami_config.loadbalancer.server.scheme=http"
    - "traefik.http.services.whoami_config.loadbalancer.server.port=80" # define the final service, which is 127.0.0.1:80 in this container
# ./traefik_dynamic_configs/dynamic.yaml
# https://doc.traefik.io/traefik/providers/file/#configuration-examples

http:
  routers:
    whoami_router:
      entryPoints:
        - web
        - websecure
      # rule: "Host(`whoami.yingshaoxo.xyz`)"
      rule: PathPrefix(`/whoami`) # yingshaoxo.xyz/whoami
      middlewares:
        - test-stripprefix
      service: service_whoami

  middlewares:
    test-stripprefix:
      stripPrefix:
        prefixes:
          - "/whoami"

  services:
    service_whoami:
      loadBalancer:
        servers:
          - url: http://whoami:80 
        passHostHeader: true
#auth.py
from flask import Flask, request

app = Flask(__name__)

@app.route("/auth")
def index():
    print(request.headers)
    return "Hello World!"

if __name__ == '__main__':
    #suppose it serves at http://host.docker.internal:1110/auth
    #which is at the host machine related to the docker container

    app.run(host="0.0.0.0", port="1110", debug=True)

Change the hosts file to simulate the DNS behavior:

#/etc/hosts

127.0.0.1 yingshaoxo.xyz whoami.yingshaoxo.xyz

Run the python file, then run docker-compose:

python auth.py &

docker-compose up

Run the following command, you shall see the python script print something out from the traefik:

# no forward auth
curl yingshaoxo.xyz/whoami/

Run the following command, you shall see the python script also print something out from the traefik:

# have forward auth
curl whoami.yingshaoxo.xyz

If you still couldn’t understand 

Give up on it, it’s not on your level

But for me, I never give up.

Here are some config files I use for GRPC:

#docker-compose
version: "3.9"

services:
  traefik:
    image: "traefik:v2.9.6"
    container_name: "traefik"
    command:
      # - "--accesslog=true"
      # - "--accessLog.filePath=/tmp/traefik_log.txt"
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.file.directory=/traefik_dynamic_configs"
      - "--providers.file.watch=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./configs/traefik_dynamic_configs:/traefik_dynamic_configs" # <== Volume for dynamic conf file

  dragonfly:
    image: docker.dragonflydb.io/dragonflydb/dragonfly
    ports:
      - '6379:6379'
    restart: unless-stopped

  # whoami:
  #   image: "traefik/whoami"
  #   expose: #expose port to other container by using http://whoami:80
  #     - "80"
  #   restart: unless-stopped

  weloveparty_account_auth_service:
    build: 
      context: ../python_user_auth_system
      dockerfile: ./Dockerfile
    image: yingshaoxo/weloveparty_account_auth_service
    expose:
      - "40051"
      - "40052"
    # ports:
    #   - "40051:40051"
    #   - "40052:40052"
    volumes:
      - type: bind
        source: ./configs/o365_token.txt
        target: /code/o365_token.txt
      - type: bind
        source: ./configs/config.py
        target: /code/src/config.py
      - ./configs/user_database:/code/data
    environment: 
      - redis_network_name=dragonfly
    restart: unless-stopped
    # labels:
    # - "traefik.enable=true"
    # - "traefik.http.routers.gost-grpc.tls=false"
    # - "traefik.http.routers.gost-grpc.rule=Host(`auth.weloveparty.domain.local`)"
    # - "traefik.http.services.gost-grpc.loadbalancer.server.port=40052"
    # - "traefik.http.services.gost-grpc.loadbalancer.server.scheme=h2c"
#./configs/traefik_dynamic_configs/traefik_dynamic_config.yaml

http:
  routers:
    grpc_auth_router:
      entryPoints:
        - web
        - websecure
      # rule: "Host(`auth.weloveparty.domain.local`)"
      rule: PathPrefix(`/auth`) 
      middlewares:
        - test-stripprefix
      service: weloveparty_account_auth_service

  middlewares:
    test-stripprefix:
      stripPrefix:
        prefixes:
          - "/auth"

  services:
    weloveparty_account_auth_service:
      loadBalancer:
        servers:
          - url: h2c://weloveparty_account_auth_service:40052
          # - url: h2c://host.docker.internal:40052
        passHostHeader: true
# /etc/hosts

127.0.0.1 weloveparty.domain.local auth.weloveparty.domain.local