Having issues with docker provider and redirect middleware

Have a router defined in my traefik-dynamic.toml that makes use of http-to-https@docker but I'm getting this error message in the logs:

  • Is there a way to validate that my traefik yaml config is valid?
  • Have I missed something moving to v2.2?
traefik       | time="2020-08-31T12:16:55Z" level=error msg="middleware \"http-to-https@docker\" does not exist" entryPointName=http routerName=synology-http@file

Here is my yaml file:

version: "3"
volumes:
  traefik:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=192.168.2.198,soft,rw,nfsvers=3,async"
      device: ":/volume1/docker/traefik"
services:
  traefik:
    container_name: traefik
    image: traefik:v2.2
    ports:
      - "80:80"
      - "443:443"
      - "9090:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /nfs/docker/traefik/traefik-dynamic.toml:/traefik-dynamic.toml
      - /nfs/docker/traefik/acme.json:/acme.json
    command:
      - "--log.level=DEBUG"

      - "--entrypoints.http.address=:80"
      - "--entrypoints.https.address=:443"

      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.watch=true"

      - "--providers.file=true"
      - "--providers.file.filename=/traefik-dynamic.toml"
      - "--providers.file.watch=true"

      - "--api=true"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--api.debug=true"

      - "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
      - "--certificatesresolvers.cloudflare.acme.email=email@gmail.com"
      - "--certificatesresolvers.cloudflare.acme.storage=acme.json"
      - "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
      - "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"

      - "--serversTransport.insecureSkipVerify=true"
    restart: always
    env_file: ./traefik.env
    labels:
      - "traefik.enable=true"

      - "traefik.http.middlewares.compress.compress=true"

      - "traefik.http.middlewares.forward-auth.forwardauth.address=http://forward-auth/auth"
      - "traefik.http.middlewares.forward-auth.forwardauth.trustForwardHeader=true"
      
      - "traefik.http.middlewares.forward-auth.forwardauth.authResponeHeader=X-Forwarded-User"

      - "traefik.http.middlewares.http-to-https.redirectscheme.scheme=https"
      - "traefik.http.middlewares.http-to-https.redirectscheme.permanent=true"
  hello:
    container_name: hello
    image: containous/whoami
    labels:
      - "traefik.enable=true"

      - "traefik.http.routers.hello-http.rule=Host(`hello.example.com`)"
      - "traefik.http.routers.hello-http.service=hello-http"
      - "traefik.http.routers.hello-http.entryPoints=http"
      - "traefik.http.routers.hello-http.tls=false"
      - "traefik.http.routers.hello-http.middlewares=compress,http-to-https"

      - "traefik.http.routers.hello-https.rule=Host(`hello.example.com`)"
      - "traefik.http.routers.hello-https.service=hello-http"
      - "traefik.http.routers.hello-https.entryPoints=https"
      - "traefik.http.routers.hello-https.tls.certresolver=cloudflare"      
      - "traefik.http.routers.hello-https.middlewares=compress"

      - "traefik.http.services.hello-http.loadbalancer.server.port=80"
  hello-auth:
    container_name: hello-auth
    image: containous/whoami
    labels:
      - "traefik.enable=true"

      - "traefik.http.routers.hello-auth-http.rule=Host(`hello-auth.example.com`)"
      - "traefik.http.routers.hello-auth-http.service=hello-auth"
      - "traefik.http.routers.hello-auth-http.entrypoints=http"
      - "traefik.http.routers.hello-auth-http.middlewares=forward-auth,compress,http-to-https"

      - "traefik.http.routers.hello-auth.rule=Host(`hello-auth.example.com`)"
      - "traefik.http.routers.hello-auth.service=hello-auth"
      - "traefik.http.routers.hello-auth.entrypoints=https"
      - "traefik.http.routers.hello-auth.tls.certresolver=cloudflare"
      - "traefik.http.routers.hello-auth.middlewares=forward-auth,compress"

      - "traefik.http.services.hello-auth.loadbalancer.server.port=80"

I see this only on startup with a docker provider middleware. But it works once the docker provider loads the config from docker labels.

Is it just the error concerning you or does it flat out not work ?

It just flat out does not work. ;(

traefik | time="2020-09-01T10:29:29Z" level=error msg="middleware "http-to-https@docker" does not exist" routerName=synology-http@file entryPointName=http

And none of the middlewares defined under the traefik service in the yaml file, show up in the dashboard.

By using the global redirection system (and with some configuration improvements)

version: "3"

volumes:
  traefik:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=192.168.2.198,soft,rw,nfsvers=3,async"
      device: ":/volume1/docker/traefik"

services:

  traefik:
    container_name: traefik
    image: traefik:v2.2
    ports:
      - 80:80
      - 443:443
      - 9090:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /nfs/docker/traefik/traefik-dynamic.toml:/traefik-dynamic.toml
      - /nfs/docker/traefik/acme.json:/acme.json
    command:
      - --log.level=INFO

      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https

      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.http.tls.certresolver=cloudflare

      - --providers.docker.exposedByDefault=false
      - --providers.docker.endpoint=unix:///var/run/docker.sock

      - --providers.file.filename=/traefik-dynamic.toml
      - --providers.file.watch=true

      - --api=true
      - --api.insecure=true

      - --certificatesresolvers.cloudflare.acme.dnschallenge=true
      - --certificatesresolvers.cloudflare.acme.email=email@gmail.com
      - --certificatesresolvers.cloudflare.acme.storage=acme.json
      - --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53
      - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare

      - --serversTransport.insecureSkipVerify=true
    restart: always
    env_file: ./traefik.env
    labels:
      traefik.enable: 'true'

      traefik.http.middlewares.compress.compress: 'true'

      traefik.http.middlewares.forward-auth.forwardauth.address: http://forward-auth/auth
      traefik.http.middlewares.forward-auth.forwardauth.trustForwardHeader: 'true'
      
      traefik.http.middlewares.forward-auth.forwardauth.authResponeHeader: X-Forwarded-User

  hello:
    container_name: hello
    image: containous/whoami
    labels:
      traefik.enable: 'true'

      traefik.http.routers.hello.rule: Host(`hello.example.com`)
      traefik.http.routers.hello.service: hello
      traefik.http.routers.hello.entryPoints: websecure,web
      traefik.http.routers.hello.middlewares: compress

      traefik.http.services.hello.loadbalancer.server.port: 80

  hello-auth:
    container_name: hello-auth
    image: containous/whoami
    labels:
      traefik.enable: 'true'

      traefik.http.routers.hello-auth.rule: Host(`hello-auth.example.com`)
      traefik.http.routers.hello-auth.service: hello-auth
      traefik.http.routers.hello-auth.entrypoints: websecure,web
      traefik.http.routers.hello-auth.middlewares: forward-auth,compress

      traefik.http.services.hello-auth.loadbalancer.server.port: 80
2 Likes

Just one nit @ldez, I believe that I'm having an issue because no hostname is specified for cert generation if I'm using dnschallenge for traefik's websecure entrypoint. Or am I missing something?

Also a million thank yous, this config is much cleaner than my katamari damacy config I've been lugging around from pre-2.0.

traefik                 | time="2020-09-02T12:31:53Z" level=error msg="Unable to obtain ACME certificate for domains \"traefik-docker\": unable to generate a certificate for the domains [traefik-docker]: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for \"traefik-docker\": Domain name needs at least one dot, url: " providerName=cloudflare.acme routerName=https-traefik-docker@docker rule="Host(`traefik-docker`)"

The behavior is expected and related to:

  traefik:
    image: traefik:v2.2
    # ...
    labels:
      traefik.enable: 'true'
      # ...

When you enable Traefik on a container, Traefik creates automatically one router and one service.
It's the same behavior when you set --providers.docker.exposedByDefault=true (the default behavior).

You have several solutions, one is to use the API in secure mode (instead of the insecure mode)

version: "3"

volumes:
  traefik:
    driver: local
    driver_opts:
      type: nfs
      o: "addr=192.168.2.198,soft,rw,nfsvers=3,async"
      device: ":/volume1/docker/traefik"

services:

  traefik:
    container_name: traefik
    image: traefik:v2.2
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /nfs/docker/traefik/traefik-dynamic.toml:/traefik-dynamic.toml
      - /nfs/docker/traefik/acme.json:/acme.json
    command:
      - --log.level=INFO

      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https

      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.http.tls.certresolver=cloudflare

      - --providers.docker.exposedByDefault=false
      - --providers.docker.endpoint=unix:///var/run/docker.sock

      - --providers.file.filename=/traefik-dynamic.toml
      - --providers.file.watch=true

      - --api=true

      - --certificatesresolvers.cloudflare.acme.dnschallenge=true
      - --certificatesresolvers.cloudflare.acme.email=email@gmail.com
      - --certificatesresolvers.cloudflare.acme.storage=acme.json
      - --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53
      - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare

      - --serversTransport.insecureSkipVerify=true
    restart: always
    env_file: ./traefik.env
    labels:
      traefik.enable: 'true'

      # Dashboard
      traefik.http.routers.traefik.rule: Host(`traefik.example.com`)
      traefik.http.routers.traefik.entrypoints: web, websecure
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.middlewares: auth

      # Middlewares
      traefik.http.middlewares.auth.basicauth.users: user:$$apr1$$q8eZFHjF$$Fvmkk//V6Btlaf2i/ju5n/ # user/password

      traefik.http.middlewares.compress.compress: 'true'

      traefik.http.middlewares.forward-auth.forwardauth.address: http://forward-auth/auth
      traefik.http.middlewares.forward-auth.forwardauth.trustForwardHeader: 'true'
      
      traefik.http.middlewares.forward-auth.forwardauth.authResponeHeader: X-Forwarded-User

  hello:
    container_name: hello
    image: containous/whoami
    labels:
      traefik.enable: 'true'

      traefik.http.routers.hello.rule: Host(`hello.example.com`)
      traefik.http.routers.hello.service: hello
      traefik.http.routers.hello.entryPoints: websecure,web
      traefik.http.routers.hello.middlewares: compress

      traefik.http.services.hello.loadbalancer.server.port: 80

  hello-auth:
    container_name: hello-auth
    image: containous/whoami
    labels:
      traefik.enable: 'true'

      traefik.http.routers.hello-auth.rule: Host(`hello-auth.example.com`)
      traefik.http.routers.hello-auth.service: hello-auth
      traefik.http.routers.hello-auth.entrypoints: websecure,web
      traefik.http.routers.hello-auth.middlewares: forward-auth,compress

      traefik.http.services.hello-auth.loadbalancer.server.port: 80

Another solution can be to use the file provider to define the "shared middlewares" instead of using the labels on the Traefik container.