I try to run traefik (using docker & swarm) and protect the dashboard using a basic auth http like this:
traefik:
image: traefik:v1.7
deploy:
# ...
labels:
- traefik.frontend.rule=Host:foo.bar.baz
- traefik.enable=true
- traefik.port=8080
- traefik.redirectorservice.frontend.entryPoints=http
- traefik.redirectorservice.frontend.redirect.entryPoint=https
- traefik.webservice.frontend.entryPoints=https
- traefik.frontend.auth.basic.users=user:password
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: >
--docker
# -...
--api
--api.statistics.recenterrors=25
It work great, but when I am on HEALTH (on foo.bar.baz/dashboard/status) I see thoses 401 (from Traefik himself):
Any idea how to fix this properly ?
Thanks
PS: for more details: https://community.containo.us/t/401-on-traefik-dashboard-health-because-of-basic-auth-http/826
Related
I have a VM which run multiple containers all linked to one docker network.
Traefik (as reverse proxy & load balancer)
cloudflared as tunnel
whoami (for testing purposes)
and some containers like photoprism, nextcloud, node-red,...
I generated an origin cert via Cloudflare which has been added to Traefik.
In Cloudflare, I have a subdomain which points via the tunnel to https://172.16.10.11 (ip from the VM). This causes an unsecure connection (IP SAN applied -> I don't think this is possible on a private ip?). When I disable TLS verification on Cloudflare, it works. However, I am trying to set this up properly. Next,I tried pointing my domain towards https://localhost. the cloudflared service running in a container cannot reach any other services as these are located other containers.
I was thinking, what if I run the cloudflared service within the Traefik container, I believe I can reach Traefik via localhost?
Do you have any advice on how to achieve a secure tunnel with cert verification? Or is this not realistic when self-hosting?
Current docker compose:
version: '3'
services:
traefik:
image: traefik:latest
command:
- --log.level=debug
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --serverstransport.insecureskipverify
- --providers.file.filename=/etc/traefik/dynamic_conf.yml
- --providers.file.watch=true
ports:
- "8080:8080"
- "443:443"
- "80:80"
networks:
- proxy_network
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefik-data:/etc/traefik
labels:
- traefik.enable=true
- traefik.docker.network=proxy_network
- traefik.http.routers.traefik.rule=Host(`${DOMAINNAME_TRAEFIK}`)
- traefik.http.routers.traefik.entrypoints=web
- traefik.http.routers.traefik.service=traefik
- traefik.http.services.traefik.loadbalancer.server.port=8080
tunnel:
container_name: cloudflared-tunnel
image: cloudflare/cloudflared
#restart: unless-stopped
networks:
- proxy_network
command: tunnel --no-autoupdate run --token ${CLOUDFLARED_TOKEN}
whoami:
image: traefik/whoami
container_name: whoami1
command:
# It tells whoami to start listening on 2001 instead of 80
- --port=2000
- --name=iamfoo
networks:
- proxy_network
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`${DOMAINNAME}`)
- traefik.http.routers.whoami.entrypoints=websecure
- traefik.http.routers.whoami.tls=true
- traefik.http.routers.whoami.service=whoami
- traefik.http.services.whoami.loadbalancer.server.port=2000
volumes:
traefik-data:
driver: local
networks:
proxy_network:
name: proxy_network
external: true
I expect a secure tunnel solution and to make sure that this architecture is setup in a good way.
On the same linux VM with docker v.19.03.11 I'm running:
Nexus:
version: '3.7'
services:
nexus:
container_name: nexus
image: sonatype/nexus3
volumes:
- nexus-data:/nexus-data
networks:
- web
ports:
- 8081
- 8082
- 8083
restart: always
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
# admin.nexus.xxx.intern
- "traefik.http.routers.nexus.rule=Host(`admin.nexus.xxx.intern`, `maven.nexus.itools.intern`)"
- "traefik.http.services.nexus.loadbalancer.server.port=8081"
- "traefik.http.routers.nexus.service=nexus"
- "traefik.http.routers.nexus.entrypoints=web"
# docker.nexus.xxx.intern
- "traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`)"
- "traefik.http.services.docker.loadbalancer.server.port=8083"
- "traefik.http.routers.docker.service=docker"
- "traefik.http.routers.docker.entrypoints=web"
networks:
web:
external: true
volumes:
nexus-data:
external: true
in Nexus Repository Manager Dashboard I created one hosted docker repository and assigned it port 8083.
and Traefik:
version: '3.7'
services:
traefik:
container_name: traefik
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./conf:/conf
- ../ssl:/ssl:ro
networks:
- web
ports:
- 80:80
- 443:443
restart: always
command:
# Enabling docker provider
- "--providers.docker=true"
# Do not expose containers unless explicitly told so
- "--providers.docker.exposedbydefault=false"
# Enable API (listening on port 8080)
- "--api.insecure=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Enable the file provider to define routers / middlewares / services in file
# EMPTY AT THE TIME!
- "--providers.file.directory=/conf"
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.rule=Host(`traefik.xxx.intern`)"
- "traefik.http.routers.traefik.entrypoints=web"
- "traefik.http.routers.traefik_tls.tls=true"
- "traefik.http.routers.traefik_tls.rule=Host(`traefik.xxx.intern`)"
- "traefik.http.routers.traefik_tls.entrypoints=websecure"
- "traefik.http.routers.traefik_tls.service=api#internal"
networks:
web:
external: true
I can login into the docker repository form anywhere:
docker login -u user -p password1234 docker.nexus.xxx.intern
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
but I cannot push into the registry:
docker push docker.nexus.xxx.intern/hello-world
The push refers to repository [docker.nexus.xxx.intern/hello-world]
af0b15c8625b: Preparing
error parsing HTTP 404 response body: invalid character 'p' after top-level value: "404 page not found\n"
When I expose the port 8083 and bypass Traefik, everything works fine and I can push into the Nexus Registry. The problem is I can only expose ports 80 and 443.
Did anyone have a similar issue and knows how to solve it?
Update 1
Have also tried with Harbor - the same result - cannot push behind traefik.
Same issue for me. I've tried
Option 1 : add prefix on path for v2 as Docker is putting a /v2 prefix
traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`) && PathPrefix(`/{version:(v1|v2)}/`)
Option 2 : add prefix to request and remove it with a middleware replacepathregex
traefik.http.middlewares.replace-path.replacepathregex.regex=^/(v1|v2)/(push|pull)/(.*)
traefik.http.middlewares.replace-path.replacepathregex.replacement=/$$1/$$3
traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`) && PathPrefix(`/{version:(v1|v2)}/push/`)
traefik.http.routers.nexus-registry-push.middlewares=replace-path
Try adding to the Nexus container in docker-compose file
environment:
- "REGISTRY_HTTP_RELATIVEURLS=true"
I'm using traefik 2.1 and would like to setup basic auth for all containers, in 1.x it was easy to do:
[entryPoints.http.auth.basic]
usersFile = "/etc/traefik/.htpasswd"
But how to setup it in 2.x? I'd like to avoid inserting code in all my docker-compose.yml files - got a lot of them.
The main idea is:
we can use built-in middleware https://docs.traefik.io/middlewares/basicauth/
we need to connect middleware from above to a container which needs to be secured
Please find an example of docker-compose.yml
version: '3.7'
services:
traefik:
image: "traefik:v2.2.1"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=default"
- "--entrypoints.web.address=:80"
- "--api"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
ports:
- 80:80
# management console
- 8080:8080
labels:
- "traefik.enable=true"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
# auth middleware with user / password
- "traefik.http.middlewares.my-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
whoami:
image: "containous/whoami"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
# connect your auth middleware to a service which you want to protect
- "traefik.http.routers.whoami.middlewares=my-auth"
So, now we can check that:
auth has prompted on http://whoami.localhost
the valid user name is "test:test" or "test2:test2"
You should use htpasswd command for generating a list of users and connect it according to the Traefik docs.
That's it. Happy coding ;)
A have traefik set up and working for a 3 node docker swarm on DigitalOcean, and my web apps are being served just fine. I want to secure the traefik dashboard, and have gleaned some info from GitHub issues, but my attempts result in a gateway timeout when trying to access the dashboard.
My compose file is below (auth & url edited for security):
version: "3.5"
services:
traefik:
image: traefik:1.6
command:
- --api
- --docker
- --docker.watch
- --docker.swarmmode
- --entryPoints=Name:http Address::80
- --entryPoints=Name:https Address::443 TLS:/run/secrets/el_cert,/run/secrets/el_key,/run/secrets/as_cert,/run/secrets/as_key
ports:
- 80:80
- 443:443
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
secrets:
- as_cert
- as_key
- el_cert
- el_key
deploy:
mode: global
labels:
- "traefik.frontend.entryPoints=http,https"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.rule=Host:<hostname>"
- "traefik.port=8080"
- "traefik.frontend.auth.basic=<user>:<password>"
placement:
constraints: [node.role==manager]
networks:
proxy:
external:
name: proxy
secrets:
as_cert:
external: true
as_key:
external: true
el_cert:
external: true
el_key:
external: true
BTW If I move the labels out from under deploy it works locally using docker-compose.
Adding the following label seems to fix things:
traefik.backend.loadbalancer.swarm=true
I presume the traefik load balancer was getting into some kind of infinite loop. I would be grateful if someone could offer a full explanation!
I am trying to use Traefik with Docker Swarm backend, and I am using the stack file below:
version: "3"
services:
traefik:
image: traefik:1.5
command: --web --docker --docker.swarmmode --docker.watch --docker.domain=sample.com --logLevel=DEBUG
deploy:
placement:
constraints: [node.role==manager]
restart_policy:
condition: on-failure
labels:
- "traefik.port=8080"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:traefik.sample.com"
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
networks:
- sample-network
portainer:
image: portainer/portainer:latest
command: --no-auth -H unix:///var/run/docker.sock
deploy:
placement:
constraints: [node.role == manager]
labels:
- "traefik.portainer.port=7777"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:portainer.sample.com"
ports:
- "7777:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- sample-network
networks:
sample-network:
I have 2 questions that I am trying to wrap my head around:
1) (Exposing Traefik dashboard through frontend rule) I can access Traefik's web dashboard on sample.com:8080, yet I cannot access it through traefik.sample.com.
2) (Port Redirection on containers/services) I can access Portainer GUI through sample.com:7777, yet I cannot access it through portainer.sample.com. I am more curious of port redirection, because how will I setup 2 services in a single stack file if I encounter 2 images publishing to the same port? My service label declarations will clash at traefik.port=XXXX
You don´t need the traefik labels on the traefik service itself. It´s accessed from the outside over the specified ports:
ports:
- "80:80"
- "8080:8080"
- "443:443"
On the portainer service you don´t need the port mappings because you probably want to route the request with traefik.
Because traefik and portainer are in the same docker network traefik can access portainer on every port.
Therefore the port for traefik have to match the real portainer port:
labels:
- "traefik.port=9000"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:portainer.sample.com"
In the current setup you have to request traefik with Host:portainer.sample.com.
You can test it with
curl --verbose --header 'Host: portainer.sample.com' 'http://<DockerhostIp>:80'
Edit: Updated curl
Edit 2: Reaction to the edit of PO
The portainer.sample.com DNS entry will have to point to your docker host. Then traefik will route it to the correct container.
An alternative is to specifiy a traefik prefix:
"traefik.frontend.rule=Host:site1.org;PathPrefixStrip: /sub/"
With the rule all requests on site1.org/sub will routed to this specific service/container.
Have a look at
Traefik-Docker-Sample
Edit 3:
The self route for the dashboard/webui should work with:
labels:
- "traefik.port=8080"
- "traefik.docker.network=sample-network"
- "traefik.frontend.rule=Host:traefik.sample.com"
Just be sure that you have a DNS entry for traefik.sample.com.
To check if the traefik setup works you can also run
curl --verbose -H Host:traefik.sample.com <DockerHostIp>