Minimale Traefik Konfiguration

3 Min Lesezeit CC BY-ND 4.0 open-source container server web

Ich habe seit Jahren einen Docker Swarm am Laufen, für den ein Traefik als Reverse Proxy, Edge Router, Ingress oder wie auch immer eins das nennen möchte, läuft. Ich bin gerade dabei Traefik und den Docker Swarm abzulösen (dazu kommt auch noch ein Blogpost). Die Traefik Doku und Nutzung war mir über die Jahre nicht gut genug, als das ich explizit bei Traefik bleiben wollen würde. Jetzt beim Rauswerfen fiel mir auf, das meine bisherige Traefik Konfiguration vergleichsweise nett ist und mal verewigt werden könnte. Dann haben vielleicht andere noch etwas davon.

Meine Konfiguration besteht aus statischer Konfiguration mittels Kommandozeilenargumenten, einer Konfigurationsdatei (für den “file provider”) und Labels an den jeweiligen Services, die freigegeben werden sollen.

Im Gegensatz zu anderen Beispielen, die ich (damals?) so fand, macht mein Setup eine automatische HTTPS Weiterleitung, ohne dass das an jedem Service wieder aktiviert werden muss.

Hinweis zu Traefik v3: Diese Konfiguration ist für Traefik v2.10. Sobald Traefik v3 veröffentlicht wird, wird es ein paar Änderungen brauchen. Leider bleibt v3 vergleichsweise umständlich, was mit ein Grund für mich ist, traefik in Zukunft nicht weiterzuverwenden.

traefik.yml (compose file)

Auskommentiert sind ein paar Optionen, die zum Testen hilfreich sind.

version: "3.7"

networks:
  net:

configs:
  dynamic:
    file: ./secrets/traefik_dynamic.yml

volumes:
  letsencrypt:

services:
  reverse-proxy:
    image: docker.io/library/traefik:v2.10
    command:
      # - --api.insecure=true # Web UI on port 8080
      # - --log.level=DEBUG
      # - --certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.myhttpchallenge.acme.email=…
      - --certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web
      - --certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entryPoint.scheme=https
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.http.middlewares=secure-headers@file
      - --entrypoints.websecure.http.tls.certResolver=myhttpchallenge
      - --entrypoints.websecure.http3
      - --experimental.http3
      - --providers.docker
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=traefik_net
      - --providers.docker.swarmMode=true
      - --providers.file.filename=/etc/traefik/dynamic.yml
    configs:
      - source: dynamic
        target: /etc/traefik/dynamic.yml
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: udp
        mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt:rw
    networks:
      - net
    deploy:
      placement:
        constraints:
          - node.role == manager

dynamic.yml

Hier werden hier die TLS Chiffren begrenzt und Security Header gesetzt. Siehe mein Post zu Qualitätschecks von Webseiten. Diese werden dann bei allen Diensten hinter dem entrypoint.websecure verwendet (via CLI konfiguriert).

tls:
  options:
    default:
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305

http:
  middlewares:
    secure-headers:
      headers:
        # https://doc.traefik.io/traefik/v2.9/middlewares/http/headers/
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        referrerPolicy: no-referrer
        stsIncludeSubdomains: true
        stsSeconds: 31536000

pro Service

Dieser Schritt passiert am häufigsten und fast jedes Mal habe ich irgendetwas vergessen. Der Service ist nicht im traefik_net oder uniquename war noch der von vor dem von irgendwo kopieren. Schon etwas unnötig nervig. Für das vergessene traefik_net kann Traefik nichts. Für die etwas umständlichen Label schon.

networks:
  traefik_net:
    external: true

services:
  bla:
    image: 
    networks:
      - default
      - traefik_net
    deploy:
      labels:
        - traefik.enable=true
        - traefik.http.services.uniquename.loadbalancer.server.port=8080
        - traefik.http.routers.uniquename.rule=Host(`….edjopato.de`)