Serving Traefik's internal dashboard behind Traefik itself

I'm in the process of migrating from v1.7 to v2.1.1. So far so good, I already have many of my containers migrated, but I can't figure out how to serve Traefik's internal dashboard (insecure mode) via Traefik itself.

Here is my traefik.yml

api:
  insecure: true

providers:
  docker:
    defaultRule: "Host(`{{ index .Labels \"com.docker.compose.service\" }}.localhost`)"
    exposedByDefault: false
    network: proxy

and here is my docker-compose.yml for the Traefik container

version: '3'
services:
  traefik:
    container_name: traefik
    image: traefik:latest
    labels:
      - traefik.enable=true
      - traefik.http.services.traefik.loadbalancer.server.port=8080
    networks:
      - proxy
    ports:
      - "80:80"
    restart: always
    volumes:
      - ./config:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro

networks:
  proxy:
    external: true

I can successfully consume Traefik's API, for instance http://traefik.localhost/api/http/routers works fine.

But when I try to access the dashboard by visiting http://traefik.localhost/dashboard/, the URL gets rewritten to http://traefik.localhost/dashboard/dashboard/dashboard/dashboard/dashboard/dashboard/... and the browser throws an error.

I can see from the API that the dashboard@internal service is being created so I've tried adding the label - traefik.http.routers.traefik.service=dashboard@internal but results are the same.

I guess I'm missing some Docker label but I cannot figure it out with the Documentation. Any advise?

Hello,

I recommend to read:

I appreciate the info, but I'm afraid none of the two links contain information regarding my problem. I don't want to secure the dashboard nor I want to leave port 8080 open in my Traefik container. I just want to know how to prevent Traefik from causing a self referencing infinite redirect to the dashboard.

The only difference I can see in the articles is they use api@internal instead of the dashboard@internal as service name which to me seems odd because the API is already working without it. I've tried anyway and the behavior is still the same.

1 Like

I've just run into this myself upgrading from 2.0 -> 2.1 where it redirects to /dashboard/dashboard/dashboard/ ...

I haven't been able to figure it out either.

EDIT: Of interest, looks like you're using docker compose, I see the same behavior on Kubernetes

1 Like

It looks like the new dashboard@internal defines its own sets of middleware that manipulate the /dashboard/:

[{
	"redirectRegex": {
		"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
		"replacement": "${1}/dashboard/",
		"permanent": true
	},
	"status": "enabled",
	"usedBy": ["dashboard@internal"],
	"name": "dashboard_redirect@internal",
	"provider": "internal",
	"type": "redirectregex"
}, {
	"stripPrefix": {
		"prefixes": ["/dashboard/", "/dashboard"]
	},
	"status": "enabled",
	"usedBy": ["dashboard@internal"],
	"name": "dashboard_stripprefix@internal",
	"provider": "internal",
	"type": "stripprefix"
}]

Now time to figure out how to get around it or redefine it.

Hi

here's what I'm using to access Traefik's dashboard :

services:
  traefik:
    command:
      - --api.dashboard=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false 
     [...]
    labels:
      traefik.enable: "true" 
      traefik.http.routers.api.rule: "Host(`traefik.mydomain.com`)"     
      traefik.http.routers.api.service: "api@internal"
      traefik.http.routers.api.entrypoints: "https"
      [...]

As you are using api.insecure the dashboard and api are exposed on 8080.

By using:

and

you are trying to create a routing for the api/dashboard.

but I recommend to not do that because this create some extra requests and can create infinite loop.

The recommended way to do that is to use api@internal and api.insecure=false.




Example 1:

api:
  dashboard: true

providers:
  docker:
    defaultRule: "Host(`{{ index .Labels \"com.docker.compose.service\" }}.localhost`)"
    exposedByDefault: false
    network: proxy
version: '3'
services:
  traefik:
    container_name: traefik
    image: traefik:v2.1.1
    labels:
      traefik.enable: true
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.entrypoints: web
    networks:
      - proxy
    ports:
      - "80:80"
    restart: always
    volumes:
      - ./config:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro

networks:
  proxy:
    external: true

Example 2:

version: "3.7"

services:
  traefik:
    image: traefik:v2.1.1
    container_name: traefik
    command:
      - --log.level=INFO
      - --entrypoints.web.address=:80
      - --api
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=proxy
      - '--providers.docker.defaultRule=Host(`{{ index .Labels "com.docker.compose.service" }}.localhost`)'
    ports:
      - "80:80"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - proxy
    labels:
      traefik.enable: true
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.entrypoints: web

networks:
  proxy:
    external: true

Also I recommend to not use image: traefik:latest but an explicit version image: traefik:v2.1.1 (or image: traefik:v2.1)

To give more information about the behavior:

I fixed the infinite loop fix: dashboard redirect loop by ldez · Pull Request #6078 · traefik/traefik · GitHub

The recommended way is still to use api@internal and api.insecure=false.