Metainformationen zur Seite
  •  

Dies ist eine alte Version des Dokuments!


Traefik

URL
https://traefik.smns-bw.org/
User
smns-tr
Passwort
••••••••••
Production
hetzner:/opt/traefik/
├── traefik
│ ├── configfiles
│ │ ├── {{:server:config.yml|config.yml}} 
│ │ ├── {{:server:middleware-chains.yml|middleware-chains.yml}} 
│ │ ├── {{:server:middlewares.yml|middlewares.yml}} 
│ │ ├── {{:server:tls-opts.yml|tls-opts.yml}}
│ ├── docker-compose.yml
│ ├── .env
│ ├── traefik.log
│ ├── traefik.yml
│ ├── access.log

In .env steht die URL traefik.smns-bw.org sowie die Zugangsdaten für diese Seite für docker-compose.yml

In die einzelnen docker-compose.yml Files der Container kommt dann sowas (Beispiel Sammlungskatalog):

    labels:
      - "traefik.http.routers.webportal.rule=Host(`${URL}`)"
      - "traefik.http.routers.webportal.entrypoints=https"
      - "traefik.http.routers.webportal.tls=true"
      - "traefik.http.routers.webportal.tls.certresolver=leresolver"
      - "traefik.http.routers.webportal.middlewares=secure-collections@file"
      - "traefik.http.services.webportal.loadbalancer.server.port=6543"
      - "traefik.http.services.webportal.loadbalancer.sticky=true"
      - "traefik.http.services.webportal.loadbalancer.sticky.cookie.name=collections.smns-bw.org"
      - "traefik.http.services.webportal.loadbalancer.sticky.cookie.httpOnly=true"
      - "traefik.http.services.webportal.loadbalancer.sticky.cookie.secure=true"
      - "traefik.docker.network=proxy"

Damit der Docker.sock nicht nach außen exposed ist, ist zusammen mit Traefik ein docker-socket aufgesetzt, der von hier stammt: https://github.com/wollomatic/socket-proxy

[1] docker-compose.yml show
services:
  traefik:
    container_name: traefik
    image: „traefik:latest“
    restart: always
#    read_only: true
    command:
      - –configfile=/traefik.yml
    mem_limit: 2G
    cpus: 0.75
    ports:
      - „80:80“
      - „443:443“
    volumes:
      - „./acme.json:/acme.json“
      - „./traefik.yml:/traefik.yml:ro“
      - „./configfiles:/configfiles:ro“
#      - „.logs/traefik.log:/traefik.log“
#      - „.logs/access.log:/access.log“
      - „./logs:/logs:rw“
    depends_on:
      - „dockerproxy“
    security_opt:
      - „no-new-privileges:true“
    networks:
      - „proxy“
      - „docker-proxynet“
    labels:
      - „traefik.http.routers.traefik.entrypoints=https“
      - „traefik.http.routers.traefik.rule=Host(`traefik.smns-bw.org`)“
      - „traefik.http.routers.traefik.tls=true“
      - „traefik.http.routers.traefik.tls.certresolver=leresolver“
      # API service
      - „traefik.http.routers.traefik.service=api@internal“
      - „traefik.http.routers.traefik.middlewares=secure-traefik@file“
      - „traefik.http.services.traefik.loadbalancer.sticky=true“
      - „traefik.http.services.traefik.loadbalancer.sticky.cookie.httpOnly=true“
      - „traefik.http.services.traefik.loadbalancer.sticky.cookie.secure=true“
    healthcheck:
      test: [„CMD“, „wget“, „–spider“, „http://localhost:8082/ping“]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

  dockerproxy:
    build:
      context: .
    container_name: socket-proxy
    command:
      - '-loglevel=DEBUG'
      - '-allowfrom=traefik,172.31.0.1'
      - '-listenip=0.0.0.0'
      - '-allowGET=/v1\..{1,2}/(version|containers/.*|events.*)'
      - '-shutdowngracetime=5'
    restart: unless-stopped
    user: „65534:998“
    read_only: true
    mem_limit: 64M
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - „proxy“
      - „docker-proxynet“
    healthcheck:
      test: [ „CMD“, „nc“, „-z“, „localhost“, „2375“ ]
      interval: 1m
      timeout: 3s
      retries: 3

  error-pages-webportal:
    container_name: error-webportal
    image: nginx:alpine
    restart: always
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./mime.types:/etc/nginx/mime.types
      - ./error-pages-webportal:/usr/share/nginx/html:ro
    labels:
      - „traefik.http.routers.error-pages-webportal.entrypoints=https“
      - „traefik.http.routers.error-pages-webportal.tls=true“
      - „traefik.http.routers.error-pages-webportal.tls.certresolver=leresolver“
      - „traefik.http.routers.error-pages-webportal.rule=Host(`error-webportal.smns-bw.org`)“
#      - „traefik.http.routers.error-pages-webportal.middlewares=secure-global@file“
      - „traefik.http.services.error-pages-webportal.loadbalancer.sticky=true“
      - „traefik.http.services.error-pages-webportal.loadbalancer.sticky.cookie.httpOnly=true“
      - „traefik.http.services.error-pages-webportal.loadbalancer.sticky.cookie.secure=true“
      - „traefik.http.services.error-pages-webportal.loadbalancer.server.port=80“
    networks:
      - „proxy“
    healthcheck:
      test: [„CMD“, „curl“, „-f“, „http://localhost/healthz.html“]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

networks:
  proxy:
    external: true
  docker-proxynet:
    driver: bridge
    internal: true


[2] traefik.yml show
entryPoints:
  http:
    address: „:80“
    http:
      redirections:
        entryPoint:
          to: ':443'
          scheme: https
  https:
    address: „:443“
#    http3:
#      advertisedPort: 443
  postgres:
    address: „:5434“
  ssh:
    address: „:666“
  healthcheck:
    address: „:8082“
log:
  level: INFO
  filePath: „/logs/traefik.log“
  format: json

accessLog:
  filePath: „/logs/access.log“
  bufferingSize: 100

api: {}

ping:
  entryPoint: healthcheck

providers:
  docker:
#    endpoint: „tcp://socket-proxy:2375“
    endpoint: „tcp://dockerproxy:2375“
#    endpoint: „unix:///var/run/docker.sock“
    watch: true
    network: proxy
#    exposedByDefault: false
  file:
    directory: „/configfiles“
    watch: true

certificatesResolvers:
  leresolver:
    acme:
      email: „it@smns-bw.org“
      storage: „/acme.json“
      caServer: „https://acme-v02.api.letsencrypt.org/directory“
      tlsChallenge: {}

experimental:
  plugins:
    traefik-plugin-cookie-path-prefix:
      moduleName: „github.com/SchmitzDan/traefik-plugin-cookie-path-prefix“
      version: „v0.0.3“
[3] config.yml show
http:
  routers:
    webmin:
      entryPoints:
        - „https“
      rule: Host(`webmin.smns-bw.org`)
      service: webmin
      middlewares:
        - „secure-webmin“
      tls:
        certResolver: leresolver
        options: tls-opts

    traefik:
      rule: Host(`traefik.smns-bw.org`)
      service: cookies

    smns_stats:
      rule: Host(`statistics.smns-bw.org`)
#      rule: „PathPrefix(`/statistics`)“
      service: smns_stats
      entryPoints:
        - „https“
      middlewares:
        - „secure-collections“
      tls:
        certResolver: leresolver
        options: tls-opts

  services:
    webmin:
      loadBalancer:
        servers:
          - url: „http://172.18.0.1:10000/“
        passHostHeader: true
        sticky:
          cookie:
            secure: true
            httpOnly: true
            sameSite: lax

    smns_stats:
      loadBalancer:
        servers:
          - url: „http://172.18.0.1:8050“
        passHostHeader: true

    cookies:
      loadBalancer:
        sticky:
          cookie:
            secure: true
            httpOnly: true
            sameSite: lax


[4] middleware-chains.yml show
http:
  middlewares:
    secure-global:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-global“

    secure-traefik:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-global“
          - „traefik-auth“

    secure-idservice:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-idservice“

    secure-biocase:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-biocase“

    secure-webmin:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-webmin“

    secure-prestashop:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-prestashop“

    secure-ent:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-ent“

    secure-collections:
      chain:
        middlewares:
          - „security-headers-collection“
          - „CSP-collections“
          - „webportal-errors“

    secure-digiphyll:
      chain:
        middlewares:
          - „security-headers-allowframes“
          - „CSP-digiphyll“

    secure-dokuwiki:
      chain:
        middlewares:
          - „security-headers-h5p“
          - „CSP-dokuwiki“

    secure-geometroidea:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-geometroidea“

    secure-h5p:
      chain:
        middlewares:
          - „security-headers-allowframes“
          - „CSP-h5p“

    secure-awstats:
      chain:
        middlewares:
          - „security-headers“
          - „CSP-awstats“

    secure-librechat:
      chain:
        middlewares:
          - „security-headers-librechat“
          - „CSP-librechat“

    secure-pictures:
      chain:
        middlewares:
          - „security-headers-allowframes“
          - „CSP-global“


[5] middlewares.yml show
http:
  middlewares:
    default-whitelist:
      ipWhiteList:
        sourceRange:
        - „127.0.0.1/32“
        - „172.19.0.0/24“

    traefik-auth:
      basicAuth:
        users:
          - „smns-tr:$2y$10$mUF04Rf7852wnP5xGxewte1hW4X/LcEN2c7of5xPOEyzbAXGVrEAi“

    security-headers-noindex:
      headers:
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlMaxAge: 100
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „none,noarchive,nosnippet,notranslate,noimageindex“
          X-Forwarded-Proto: „https“
          Server: „“
          x-powered-by: „“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
          customFrameOptionsValue: SAMEORIGIN
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
        stsSeconds: 31536000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), payment=()
        frameDeny: true

    security-headers:
      headers:
        accessControlMaxAge: 100
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „index, follow“
          X-Forwarded-Proto: „https“
          Server: „“
          accessControlAllowMethods:
            - GET
            - OPTIONS
            - PUT
          accessControlAllowHeaders: „*“
          X-Powered-By: „“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
          customFrameOptionsValue: „ALLOW-FROM https://smns-bw.org“
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
        stsSeconds: 31536000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), payment=()
        frameDeny: true

    security-headers-allowframes:
      headers:
        accessControlMaxAge: 100
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „index, follow“
          accessControlAllowMethods:
            - GET
            - OPTIONS
            - PUT
          X-Forwarded-Proto: „https“
          Server: „“
          X-Powered-By: „“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
          CustomFrameOptionsValue: „ALLOW-FROM https://smns-bw.org“
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsSeconds: 63072000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), payment=()

    security-headers-collection:
      headers:
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „index, follow“
          X-Forwarded-Proto: „https“
          Server: „“
          accessControlAllowMethods:
            - GET
            - OPTIONS
            - PUT
          accessControlAllowHeaders: „*“
          accessControlAllowOriginList:
            - https://pydeepzoom.smns-bw.org
            - https://pictures.smns-bw.org
          accessControlMaxAge: 100
#          customFrameOptionsValue: „ALLOW-FROM https://pictures.smns-bw.org“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsSeconds: 63072000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), payment=()
#        x-frame-options: ALLOW-FROM https://pictures.smns-bw.org

    security-headers-librechat:
      headers:
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlMaxAge: 100
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „none,noarchive,nosnippet,notranslate,noimageindex“
          X-Forwarded-Proto: „https“
          server: „“
          x-powered-by: „“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
          customFrameOptionsValue: SAMEORIGIN
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
#        stsIncludeSubdomains: true
#        stsSeconds: 63072000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), ambient-light-sensor=(), gyroscope=(), payment=()
        frameDeny: true

    security-headers-h5p:
      headers:
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlMaxAge: 100
        addVaryHeader: true
        customResponseHeaders:
          X-Robots-Tag: „none,noarchive,nosnippet,notranslate,noimageindex“
          X-Forwarded-Proto: „https“
          server: „“
        customRequestHeaders:
          X-Forwarded-Proto: „https“
          Cache-Control: public
          customFrameOptionsValue: SAMEORIGIN
        sslProxyHeaders:
          X-Forwarded-Proto: „https“
          sslRedirect: true
        referrerPolicy: „same-origin“
        hostsProxyHeaders:
          - „X-Forwarded-Host“
        contentTypeNosniff: true
        browserXssFilter: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsSeconds: 63072000
        stsPreload: false
        permissionsPolicy: fullscreen=(self „https://smns-bw.org“), geolocation=*, midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), vr=(), speaker=(), ambient-light-sensor=(), gyroscope=(), microphone=(), payment=()
        frameDeny: false

    CSP-global:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org; frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org; base-uri 'self';
          form-action 'self'; img-src 'self' data:;
          connect-src 'self'; font-src 'self';
          style-src 'self' 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;

    CSP-dokuwiki:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org *.google.com;
          base-uri 'self';
          form-action 'self';
          img-src 'self' https://www.dokuwiki.org https://www.gravatar.com data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;

    CSP-idservice:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org; frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' https://physalia.evolution.uni-bonn.de data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org https://physalia.evolution.uni-bonn.de;

    CSP-librechat:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' blob: data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;

    CSP-awstats:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' https://chart.googleapis.com;
          connect-src 'self' https://www.gstatic.com/charts/;
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          style-src-elem https://www.gstatic.com/charts/ 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          script-src-elem https://www.google.com/jsapi https://www.gstatic.com/charts/ 'unsafe-inline' 'unsafe-eval';

    CSP-h5p:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors https://www.naturkundemuseum-bw.de;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;

    CSP-biocase:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' https://unpkg.com/ https://*.tile.osm.org data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline' https://unpkg.com/leaflet@1.3.3/dist/leaflet.css;
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org https://unpkg.com/leaflet@1.3.3/dist/leaflet.js https://code.jquery.com/jquery-1.7.min.js;

    CSP-prestashop:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          img-src 'self' data:;
          connect-src 'self';
          font-src 'self';
          style-src 'self' 'unsafe-inline';
          style-src-elem https://market.smns-bw.org/;
          script-src 'self' 'unsafe-inline' 'unsafe-eval' https://market.smns-bw.org/;

    CSP-webmin:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          img-src 'self' data:;
          font-src 'self' *.smns-bw.org data:;

    CSP-collections:
      headers:
        contentSecurityPolicy: >
          default-src 'none';
          frame-ancestors 'self' *.smns-bw.org pictures.smns-bw.org;
          frame-src *.smns-bw.org;
          base-uri 'self';
          form-action 'self';
          style-src 'self' 'unsafe-inline' *.smns-bw.org https://cloud.ccm19.de;
          connect-src 'self' https://cloud.ccm19.de https://matomo.naturkundemuseum-bw.de/;
          font-src 'self' *.smns-bw.org;
          img-src 'self' data *.smns-bw.org https://a.tile.openstreetmap.org https://b.tile.openstreetmap.org https://c.tile.openstreetmap.org https://cloud.ccm19.de data:;
          script-src 'self' 'unsafe-inline' 'unsafe-eval' https://pydeepzoom.smns-bw.org https://matomo.naturkundemuseum-bw.de https://cloud.ccm19.de;

    CSP-ent:
      headers:
        contentSecurityPolicy: >
          default-src 'none';
          base-uri 'self';
          form-action 'self';
          style-src-elem https://ent.smns-bw.org/static/css/ 'unsafe-inline';
          connect-src 'self' 'unsafe-inline' https://matomo.naturkundemuseum-bw.de;
          script-src-elem 'self' 'unsafe-inline' 'unsafe-eval' https://matomo.naturkundemuseum-bw.de https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js https://openseadragon.github.io/openseadragon/openseadragon.js;
          img-src 'self' https://openseadragon.github.io/openseadragon/images/;

    CSP-digiphyll:
      headers:
        contentSecurityPolicy: >
          default-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org;
          frame-ancestors 'self' *.smns-bw.org;
          frame-src *.smns-bw.org https://144.41.33.40/;
          base-uri 'self';
          form-action 'self';
          img-src 'self' https://a.tile.openstreetmap.org https://b.tile.openstreetmap.org https://c.tile.openstreetmap.org https://unpkg.com/ data:;
          connect-src 'self';
          font-src 'self' data:;
          style-src 'self' 'unsafe-inline' data:;
          script-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org https://mathjax.rstudio.com/latest/ http://144.41.33.40/ data:;

    CSP-geometroidea:
      headers:
        contentSecurityPolicy: >
          default-src 'self';
          style-src 'self' 'unsafe-inline' 'unsafe-eval' *.smns-bw.org https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css https://fonts.googleapis.com/css2;
          font-src 'self' https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/webfonts/ https://fonts.gstatic.com/s/nunito/v25/;
          img-src 'self' data:;

    my-traefik-plugin-cookie-path-prefix:
      plugin:
        traefik-plugin-cookie-path-prefix:
          prefix: smns

    webportal-errors:
      errors:
        status:
          - „404-503“
        service: error-pages-webportal@docker
        query: „/{status}.html“

#    another-service-errors:
#      errors:
#        status:
#          - „404-503“
#        service: error-pages-another-service
#        query: „/error-pages-another-service/{status}.html“


[6] tls-opts.yml show
tls:
  options:
    tls-opts:
      minVersion: VersionTLS12
      cipherSuites:
        - „TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256“
        - „TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256“
        - „TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384“
        - „TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384“
        - „TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305“
        - „TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305“
      curvePreferences:
        - CurveP521
        - CurveP384
#      sniStrict: true

Traefik v3 Healthcheck (Docker)

Overview

This page describes how to set up a robust Docker healthcheck for Traefik v3.x.

It covers recent Traefik changes, the “gotchas” with TLS, and provides full configuration (compose and YAML) for reliable service monitoring.

Why Do I Need a Special Healthcheck for Traefik 3?

  • As of Traefik 3, the /ping endpoint (Traefik's native health endpoint) can only be bound to a non-TLS (HTTP/plaintext) entrypoint.
  • Any attempt to bind /ping to a TLS entrypoint (e.g., :443) causes it to be unavailable and will not log an error!
  • Many guides and blog posts referencing Traefik 2.x are now out of date.
  • Docker healthchecks are only updated when containers are recreated.

Step-by-Step Setup

1. Add a dedicated HTTP (non-TLS) entrypoint for health

Add this to your traefik.yml:

entryPoints:
  healthcheck:
    address: ":8082"

ping:
  entryPoint: healthcheck
  • Use any unused high port (8082 is common and outside process-bound port ranges).
  • Do not enable TLS or configure HTTP redirection for this entrypoint.
2. Update ''docker-compose.yml'' healthcheck section
healthcheck:
  test: [ "CMD", "wget", "--spider", "http://localhost:8082/ping" ]
  interval: 30s
  timeout: 5s
  retries: 3
  start_period: 10s
3. Recreate the container (!important)

After editing the healthcheck, you must remove and recreate the container to apply the updated check.

 docker compose down docker compose up -d

or for just the traefik service:

 docker compose rm traefik docker compose up -d traefik
4. Confirm it's working
  • Check status with:
 docker inspect traefik | grep Health -A 10
 wget --spider http://localhost:8082/ping
  • and expect “remote file exists” or HTTP 200.

Troubleshooting

  • If you see '404 Not Found' or status stays unhealthy, check:
    • The entryPoint in ping and traefik.yml matches (healthcheck)
    • Logs for ping endpoint registration (grep -i ping <traefik.log>)
    • Healthcheck in the running container is updated (see docker inspect)
  • If the healthcheck is still using the old endpoint (e.g., port 443), the container must be removed and recreated.

FAQ

  • Q: Why not use /ping on :443?
    • A: Traefik 3.x forbids it; /ping only works on a non-TLS (HTTP) entrypoint.
  • Q: Do I need to expose port 8082 externally?
    • A: No; healthchecks run inside the container.
  • Q: Can I combine ping and redirect on the same entrypoint?
    • A: No; keep your healthcheck entrypoint plain.

References