I need help on securing Traefik dashboard, the config file below, I am getting 404 not found on both foo.bar/dashboard and foo.bar.
version: "3.3"
networks:
proxy:
external: true
volumes:
log:
external: true
letsencrypt:
configs:
traefik_users:
file: /path/to/users/file/users
services:
traefik:
image: traefik:v2.2.1
configs:
- source: traefik_users
target: /users
mode: 444
ports:
- "80:80"
- "443:443"
command:
- --api.insecure=false
- --api.dashboard=true
- --api
- --accesslog=true
- --accesslog.filepath=/var/log/traefik/traefik.log
- --accesslog.bufferingsize=100
- --log.level=ERROR
- --providers.docker=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --entrypoints.ep-http.address=:80
- --entrypoints.ep-https.address=:443
# - --certificatesresolvers.certresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
- --certificatesresolvers.certresolver.acme.caServer=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.certresolver.acme.tlschallenge=true
- --certificatesresolvers.certresolver.acme.email=foo.bar@foo.bar
- --certificatesresolvers.certresolver.acme.storage=/letsencrypt/acme.json
volumes:
- log:/var/log
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
deploy:
replicas: 1
restart_policy:
condition: any
delay: 3s
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.routers.r-redirect-to-https.rule=hostregexp(`{host:.+}`)
- traefik.http.routers.r-redirect-to-https.entrypoints=ep-http
- traefik.http.routers.r-redirect-to-https.middlewares=mw-redirect-to-https
- traefik.http.middlewares.mw-redirect-to-https.redirectscheme.scheme=https
- traefik.http.middlewares.mw-traefik-auth.digestauth.usersfile=/users
- traefik.http.routers.r-traefik.service=api@internal
- traefik.http.routers.r-traefik.rule=Host(`foo.bar`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
- traefik.http.routers.r-traefik.entrypoints=ep-https
- traefik.http.routers.r-traefik.tls=true
- traefik.http.routers.r-traefik.tls.certresolver=certresolver
- traefik.http.routers.r-traefik.middlewares=mw-traefik-auth
And the 2d question - I wanted to run Traefik dashboard on a prefix foo.bar:/traefik - how would I let Traefik know that it runs on the prefix? I have tried to prepend the PathPrefixes with /traefik, then stripped the /traefik prefix, but how would I then inform Traefik dashboard that it runs behind a reverse proxy on the /traefik prefix?
Thanks a lot
cakiwi
May 23, 2020, 11:29pm
2
Incorrect format, put the whole rule in () like:
- traefik.http.routers.r-traefik.rule=(Host(`foo.bar`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`)))
cakiwi
May 23, 2020, 11:32pm
3
yolkhovyy:
And the 2d question - I wanted to run Traefik dashboard on a prefix foo.bar:/traefik - how would I let Traefik know that it runs on the prefix? I have tried to prepend the PathPrefixes with /traefik, then stripped the /traefik prefix, but how would I then inform Traefik dashboard that it runs behind a reverse proxy on the /traefik prefix?
Per the docs the rule has to match /api/
and /dashboard
@cakiwi - thanks for your quick responses!
I've tried to add parentheses - no changes, still 404. Here is my current config file:
version: "3.3"
networks:
proxy:
external: true
volumes:
log:
external: true
opench_portainer:
external: true
letsencrypt:
configs:
traefik_users:
file: /home/pi/data/traefik_users/users
services:
traefik:
image: traefik:v2.2.1
configs:
- source: traefik_users
target: /users
mode: 444
ports:
- "80:80"
- "443:443"
command:
- --api.insecure=false # set to 'false' on production
- --api.dashboard=true # see https://docs.traefik.io/v2.0/operations/dashboard/#secure-mode for how to secure the dashboard
- --api
- --accesslog=true
- --accesslog.filepath=/var/log/traefik/traefik.log
- --accesslog.bufferingsize=100
- --log.level=ERROR
- --providers.docker=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --entrypoints.ep-http.address=:80
- --entrypoints.ep-https.address=:443
- --certificatesresolvers.certresolver.acme.caServer=https://acme-v02.api.letsencrypt.org/directory
- --certificatesresolvers.certresolver.acme.tlschallenge=true
- --certificatesresolvers.certresolver.acme.email=foo.bar@foo.bar - --certificatesresolvers.certresolver.acme.storage=/letsencrypt/acme.json
volumes:
- log:/var/log
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
deploy:
replicas: 1
restart_policy:
condition: any
delay: 3s
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.middlewares.mw-redirect-to-https.redirectscheme.scheme=https
- traefik.http.middlewares.mw-redirect-to-https.redirectscheme.permanent=true
- traefik.http.routers.r-redirect-to-https.rule=hostregexp(`{host:.+}`)
- traefik.http.routers.r-redirect-to-https.entrypoints=ep-http
- traefik.http.routers.r-redirect-to-https.middlewares=mw-redirect-to-https
- traefik.http.services.dummy-service.loadbalancer.server.port=1357
- traefik.http.routers.r-traefik.service=api@internal
- traefik.http.routers.r-traefik.rule=(Host(`foo.bar`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`)))
- traefik.http.routers.r-traefik.entrypoints=ep-https
- traefik.http.routers.r-traefik.tls=true
- traefik.http.routers.r-traefik.tls.certresolver=certresolver
Weird. I took your previous compose , removed the certresolver(only running locally) and updated the rule.
Ran like a charm.
Maybe switch up the logging to DEBUG to see what is going on.
version: "3.3"
networks:
proxy:
# external: true
volumes:
log:
# external: true
letsencrypt:
configs:
traefik_users:
file: ./users
services:
traefik:
image: traefik:v2.2.1
configs:
- source: traefik_users
target: /users
mode: 444
ports:
- "80:80"
- "443:443"
command:
- --api.insecure=false
- --api.dashboard=true
- --api
- --accesslog=true
# - --accesslog.filepath=/var/log/traefik/traefik.log
- --accesslog.bufferingsize=100
- --log.level=INFO
- --providers.docker=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --entrypoints.ep-http.address=:80
- --entrypoints.ep-https.address=:443
# - --certificatesresolvers.certresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
# - --certificatesresolvers.certresolver.acme.caServer=https://acme-v02.api.letsencrypt.org/directory
# - --certificatesresolvers.certresolver.acme.tlschallenge=true
# - --certificatesresolvers.certresolver.acme.email=foo.bar@foo.bar
# - --certificatesresolvers.certresolver.acme.storage=/letsencrypt/acme.json
volumes:
- log:/var/log
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
deploy:
replicas: 1
restart_policy:
condition: any
delay: 3s
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.middlewares.mw-redirect-to-https.redirectscheme.scheme=https
- traefik.http.middlewares.mw-redirect-to-https.redirectscheme.permanent=true
- traefik.http.routers.r-redirect-to-https.rule=hostregexp(`{host:.+}`)
- traefik.http.routers.r-redirect-to-https.entrypoints=ep-http
- traefik.http.routers.r-redirect-to-https.middlewares=mw-redirect-to-https
- traefik.http.services.dummy-service.loadbalancer.server.port=1357
- traefik.http.routers.r-traefik.service=api@internal
- traefik.http.routers.r-traefik.rule=(Host(`foo.bar`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`)))
- traefik.http.routers.r-traefik.entrypoints=ep-https
- traefik.http.routers.r-traefik.tls=true
# - traefik.http.routers.r-traefik.tls.certresolver=certresolver
curl -ik https://foo.bar/api/rawdata --resolve foo.bar:443:127.0.0.1
HTTP/2 200
content-type: application/json
content-length: 957
date: Sun, 24 May 2020 15:51:31 GMT
{"routers":{"r-redirect-to-https@docker":{"entryPoints":["ep-http"],"middlewares":["mw-redirect-to-https@docker"],"service":"dummy-service","rule":"hostregexp(`{host:.+}`)","status":"enabled","using":["ep-http"]},"r-traefik@docker":{"entryPoints":["ep-https"],"service":"api@internal","rule":"(Host(`foo.bar`) \u0026\u0026 (PathPrefix(`/dashboard`) || PathPrefix(`/api`)))","tls":{},"status":"enabled","using":["ep-https"]}},"middlewares":{"mw-redirect-to-https@docker":{"redirectScheme":{"scheme":"https","permanent":true},"status":"enabled","usedBy":["r-redirect-to-https@docker"]}},"services":{"api@internal":{"status":"enabled","usedBy":["r-traefik@docker"]},"dashboard@internal":{"status":"enabled"},"dummy-service@docker":{"loadBalancer":{"servers":[{"url":"http://10.0.0.26:1357"}],"passHostHeader":true},"status":"enabled","usedBy":["r-redirect-to-https@docker"],"serverStatus":{"http://10.0.0.26:1357":"UP"}},"noop@internal":{"status":"enabled"}}}
/api/rawdata works for me too, but /dashboard returns 404 in the browser.
Here is what /api/rawdata returns:
"services": {
"api@internal": {
"status": "enabled",
"usedBy": [
"r-traefik@docker"
]
},
"dashboard@internal": {
"status": "enabled"
},
"dummy-service@docker": {
"loadBalancer": {
"servers": [
{
"url": "[http://10.0.0.26:1357](http://10.0.0.26:1357)"
}
],
"passHostHeader": true
},
"status": "enabled",
"usedBy": [
"r-redirect-to-https@docker"
],
"serverStatus": {
"[http://10.0.0.26:1357](http://10.0.0.26:1357)": "UP"
}
},
"noop@internal": {
"status": "enabled"
}
}
I do not understand how the r-traefik router can route /dashboard request to dashboard@internal - there is no "usedBy" field in the dashboard@internal.
Another thing that I do not understand - why the dummy-service is needed. I saw it in examples on internet, without it the /api/rawdata does not work, although the api@internal does have the "usedBy" field anyway.
Just discovered that if I change the order of the endpoints in the rule - /dashboard works.
- traefik.http.routers.r-traefik.rule=(Host(`foo.bar`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)))
1 Like
It stopped working after I tried:
to use digest authentication - got in an endless login popup loop
had to switch back to basic authenticaion
secured traefik stopped working
At the end I found a reliable solution - trailing slashes in the router rules, this works so far:
- traefik.http.routers.r-traefik.rule=(Host(`foo.bar`) && (PathPrefix(`/api/`) || PathPrefix(`/dashboard/`)))
Used trailing slashes also in the corresponding DNS record, though not sure if it was needed.