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.

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

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.