tcurdt
October 30, 2019, 2:12am
1
I am a little lost trying to get the following working:
a single http service on port 5151 exposed as https on 443
a self signed cert when trying locally, letsencrypt for production
protected path /foo by a client cert (if possible)
I started with the following:
version: '3.7'
services:
web:
image: traefik:2.0.4
restart: unless-stopped
command:
- "--api.insecure=true"
- "--global.sendAnonymousUsage=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=true"
- "--entryPoints.https.address=:443"
# - "--certificatesResolvers.letsencrypt.acme.httpChallenge=true"
# - "--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=https"
# - "--certificatesresolvers.letsencrypt.acme.email=XXXXXXXXX"
# - "--certificatesresolvers.letsencrypt.acme.storage=/opt/traefik/acme.json"
ports:
- 443:443
- 127.0.0.1:8080:8080
networks:
- local
depends_on:
- backend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/certs:ro
backend:
image: containous/whoami # just for testing
restart: unless-stopped
ports:
- 5151:80 # real backend will have 5151:5151
labels:
- "traefik.port=5151"
- "traefik.http.routers.backend-https.rule=Host(`machine.test`)"
- "traefik.http.routers.backend-https.entrypoints=https"
# - "traefik.http.routers.backend-https.tls.certresolver=letsencrypt"
networks:
local:
Where I am struggling:
howto add a self signed cert
verify letsencrypt is working like this
howto require a client cert for /foo
Can anyone point me at least into the right direction?
Thanks!
ldez
October 30, 2019, 8:07am
2
1 Like
tcurdt
October 30, 2019, 10:23am
3
Super helpful article - thanks!
Unfortunately it does not cover my open questions.
I am still not sure how to specify the following via labels:
[[tls.certificates]]
certFile = "/path/to/domain.cert"
keyFile = "/path/to/domain.key"
[tls.options]
[tls.options.default]
[tls.options.default.clientAuth]
caFiles = ["tests/clientca1.crt", "tests/clientca2.crt"]
clientAuthType = "RequireAndVerifyClientCert"
and how to make the client cert only apply for a certain path.
tcurdt
October 30, 2019, 10:48am
5
I read this as "it's not possible to pass as parameters/labels - it must be defined in a file". IIUC I can only use --providers.file.filename
to specify that instead?
But that will not help me to apply the client cert only to path /foo
.
tcurdt
November 1, 2019, 10:18am
6
Is this correct? The paths to the certs must be specified in a file?
tcurdt
November 1, 2019, 10:23am
7
For letsencrypt support I came up with
version: '3.7'
services:
web:
image: traefik:2.0.4
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=true"
- "--entryPoints.https.address=:443"
- "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.letsencrypt.acme.email=me@foo.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/vol/acme.json"
- "--certificatesResolvers.letsencrypt.acme.tlsChallenge=true"
ports:
- 443:443
networks:
- local
depends_on:
- backend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./vol/traefik:/vol
backend:
image: containous/whoami
command:
- "--port=5678"
restart: unless-stopped
labels:
- "traefik.http.routers.backend-https.rule=Host(`foo.com`)"
- "traefik.http.routers.backend-https.entrypoints=https"
- "traefik.http.services.backend-https.loadbalancer.server.port=5678"
- "traefik.http.routers.backend-https.tls.certresolver=letsencrypt"
networks:
local:
but not I am not sure what's wrong with that config. It's giving me a 404.
Any advice? Thanks!
tcurdt
November 1, 2019, 1:06pm
8
Update with the DEBUG log:
version: '3.7'
services:
web:
image: traefik:2.0.4
restart: unless-stopped
command:
- "--log.level=DEBUG"
- "--providers.docker=true"
- "--entryPoints.https.address=:443"
ports:
- 443:443
networks:
- local
depends_on:
- backend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
backend:
image: containous/whoami
command:
- "--port=5678"
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.entrypoints=https"
- "traefik.http.routers.backend.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.services.backend.loadbalancer.server.port=5678"
networks:
local:
Produces:
backend_1 | Starting up on port 5678
web_1 | time="2019-11-01T12:57:53Z" level=info msg="Configuration loaded from flags."
web_1 | time="2019-11-01T12:57:53Z" level=info msg="Traefik version 2.0.4 built on 2019-10-28T20:23:57Z"
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Static configuration loaded {\"global\":{\"checkNewVersion\":true},\"serversTransport\":{\"maxIdleConnsPerHost\":200},\"entryPoints\":{\"https\":{\"address\":\":443\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":10000000000},\"respondingTimeouts\":{\"idleTimeout\":180000000000}},\"forwardedHeaders\":{}}},\"providers\":{\"providersThrottleDuration\":2000000000,\"docker\":{\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"exposedByDefault\":true,\"swarmModeRefreshSeconds\":15000000000}},\"log\":{\"level\":\"DEBUG\",\"format\":\"common\"}}"
web_1 | time="2019-11-01T12:57:53Z" level=info msg="\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://docs.traefik.io/v2.0/contributing/data-collection/\n"
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="No default certificate, generating one"
web_1 | time="2019-11-01T12:57:53Z" level=info msg="Starting provider aggregator.ProviderAggregator {}"
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Start TCP Server" entryPointName=https
web_1 | time="2019-11-01T12:57:53Z" level=info msg="Starting provider *docker.Provider {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"exposedByDefault\":true,\"swarmModeRefreshSeconds\":15000000000}"
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Provider connection established with docker 19.03.2 (API 1.40)" providerName=docker
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Configuration received from provider docker: {\"http\":{\"routers\":{\"backend\":{\"entryPoints\":[\"https\"],\"service\":\"backend\",\"rule\":\"HostRegexp(`{host:.+}`)\"},\"web-traefik\":{\"service\":\"web-traefik\",\"rule\":\"Host(`web-traefik`)\"}},\"services\":{\"backend\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.20.0.2:5678\"}],\"passHostHeader\":true}},\"web-traefik\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.21.0.2:80\"}],\"passHostHeader\":true}}}},\"tcp\":{}}" providerName=docker
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="No entryPoint defined for this router, using the default one(s) instead: [https]" routerName=web-traefik@docker
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating middleware" middlewareName=pipelining middlewareType=Pipelining entryPointName=https routerName=web-traefik@docker serviceName=web-traefik
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating load-balancer" entryPointName=https routerName=web-traefik@docker serviceName=web-traefik
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating server 0 http://172.21.0.2:80" routerName=web-traefik@docker serviceName=web-traefik serverName=0 entryPointName=https
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Added outgoing tracing middleware web-traefik" routerName=web-traefik@docker middlewareName=tracing middlewareType=TracingForwarder entryPointName=https
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating middleware" serviceName=backend middlewareName=pipelining middlewareType=Pipelining entryPointName=https routerName=backend@docker
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating load-balancer" serviceName=backend entryPointName=https routerName=backend@docker
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating server 0 http://172.20.0.2:5678" routerName=backend@docker serviceName=backend serverName=0 entryPointName=https
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Added outgoing tracing middleware backend" entryPointName=https routerName=backend@docker middlewareType=TracingForwarder middlewareName=tracing
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="Creating middleware" middlewareType=Recovery entryPointName=https middlewareName=traefik-internal-recovery
web_1 | time="2019-11-01T12:57:53Z" level=debug msg="No default certificate, generating one"
$ curl -k -I https://localhost
HTTP/2 404
content-type: text/plain; charset=utf-8
x-content-type-options: nosniff
content-length: 19
date: Fri, 01 Nov 2019 12:58:05 GMT
web_1 | time="2019-11-01T12:58:05Z" level=debug msg="Serving default certificate for request: \"localhost\""
Please - any pointers? Thanks.
PS: Why is web-traefik
being created?
ldez
November 2, 2019, 11:04pm
9
It's related to Docker | Traefik | v2.0
A simple TLS example:
version: '3.7'
services:
web:
image: traefik:v2.0.4
command:
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --api=true
- --log.level=INFO
- --providers.docker=true
- --providers.docker.exposedbydefault=false
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.traefik.rule=Host(`traefik.docker.localhost`)"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls=true"
# global redirect HTTPS
- "traefik.http.routers.catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.catchall.entrypoints=web"
- "traefik.http.routers.catchall.middlewares=redirecthttps"
# redirect HTTPS
- "traefik.http.middlewares.redirecthttps.redirectscheme.scheme=https"
backend:
image: containous/whoami
command:
- "--port=5678"
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=Host(`whoami.docker.localhost`)"
- "traefik.http.routers.backend.entrypoints=websecure"
- "traefik.http.routers.backend.tls=true"
- "traefik.http.services.backend.loadbalancer.server.port=5678"
tcurdt
November 2, 2019, 11:48pm
10
Thanks for the example, @ldez - but that's giving me the very same 404.
I've adopted it to strip out the dashboard and port 80 and to make it even simpler - but are still getting a 404.
version: '3.7'
services:
web:
image: traefik:2.0.4
restart: unless-stopped
command:
- "--entryPoints.https.address=:443"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--log.level=DEBUG"
ports:
- 443:443
depends_on:
- backend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
backend:
image: containous/whoami
command:
- "--port=5678"
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.backend.entrypoints=https"
- "traefik.http.routers.backend.tls=true"
- "traefik.http.services.backend.loadbalancer.server.port=5678"
Something is really off here.
ldez
November 3, 2019, 12:13am
11
Your example is working:
version: '3.7'
services:
web:
image: traefik:2.0.4
command:
- "--entryPoints.https.address=:443"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--log.level=DEBUG"
ports:
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
backend:
image: containous/whoami
command:
- "--port=5678"
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.backend.entrypoints=https"
- "traefik.http.routers.backend.tls=true"
- "traefik.http.services.backend.loadbalancer.server.port=5678"
https://localhost -> whoami
$ curl -k https://localhost
Hostname: cea44e30ae28
IP: 127.0.0.1
IP: 172.23.0.2
RemoteAddr: 172.23.0.3:55778
GET / HTTP/1.1
Host: localhost
User-Agent: curl/7.66.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.23.0.1
X-Forwarded-Host: localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: d50b7420c3ca
X-Real-Ip: 172.23.0.1
I recommend to clean your networks: docker prune network
Are you using swarm?
tcurdt
November 3, 2019, 12:50am
12
Odd. It's not working here:
$ docker network prune
$ docker-compose up
$ curl -k https://localhost
404 page not found
$ docker -v
Docker version 19.03.2, build 6a30dfc
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b
ldez
November 3, 2019, 12:57am
13
$ docker -v
Docker version 19.03.4-ce, build 9013bf583a
$ docker-compose -v
docker-compose version 1.24.1, build unknown
$ drill localhost
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 36499
;; flags: qr aa rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; localhost. IN A
;; ANSWER SECTION:
localhost. 0 IN A 127.0.0.1
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 4 msec
;; SERVER: 192.168.1.1
;; WHEN: Sun Nov 3 01:55:23 2019
;; MSG SIZE rcvd: 43
$ curl -k -H Host:localhost https://127.0.0.1
Hostname: cea44e30ae28
IP: 127.0.0.1
IP: 172.23.0.2
RemoteAddr: 172.23.0.3:57072
GET / HTTP/1.1
Host: localhost
User-Agent: curl/7.66.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.23.0.1
X-Forwarded-Host: localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: d50b7420c3ca
X-Real-Ip: 172.23.0.1
$ curl -k -H Host:test https://127.0.0.1
Hostname: cea44e30ae28
IP: 127.0.0.1
IP: 172.23.0.2
RemoteAddr: 172.23.0.3:57072
GET / HTTP/1.1
Host: test
User-Agent: curl/7.66.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.23.0.1
X-Forwarded-Host: test
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: d50b7420c3ca
X-Real-Ip: 172.23.0.1
tcurdt
November 3, 2019, 1:06am
14
Given that it is https and the only reachable when the containers are up it really must be traefik
returning the 404 (on my machine).
$ curl -k -H Host:localhost https://127.0.0.1
404 page not found
Plus I see this request in the logs with level DEBUG:
web_1 | time="2019-11-03T01:04:06Z" level=debug msg="Serving default certificate for request: \"\""
Any further ideas on how debug this, @ldez ?
ldez
November 3, 2019, 1:10am
15
The log is not a problem (I got the same).
Could you try this:
version: '3.7'
services:
web:
image: traefik:2.0.4
command:
- "--entryPoints.https.address=:443"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--log.level=DEBUG"
ports:
- 443:443
- 8080:8080
depends_on:
- backend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
backend:
image: containous/whoami
command:
- "--port=5678"
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.backend.entrypoints=https"
- "traefik.http.routers.backend.tls=true"
- "traefik.http.services.backend.loadbalancer.server.port=5678"
and call the API:
$ curl -s http://127.0.0.1:8080/api/rawdata | jq
{
"routers": {
"backend@docker": {
"entryPoints": [
"https"
],
"service": "backend",
"rule": "HostRegexp(`{host:.+}`)",
"tls": {},
"status": "enabled",
"using": [
"https"
]
}
},
"services": {
"backend@docker": {
"loadBalancer": {
"servers": [
{
"url": "http://172.23.0.2:5678"
}
],
"passHostHeader": true
},
"status": "enabled",
"usedBy": [
"backend@docker"
],
"serverStatus": {
"http://172.23.0.2:5678": "UP"
}
}
}
}
tcurdt
November 3, 2019, 1:25am
16
Just to be sure I updated docker to the same version:
Docker version 19.03.4, build 9013bf5
Then started your latest docker compose file
$ curl -s http://127.0.0.1:8080/api/rawdata | jq
{
"routers": {
"backend@docker": {
"entryPoints": [
"https"
],
"service": "backend",
"rule": "HostRegexp(`{host:.+}`)",
"tls": {},
"status": "enabled",
"using": [
"https"
]
}
},
"services": {
"backend@docker": {
"loadBalancer": {
"servers": [
{
"url": "http://172.23.0.2:5678"
}
],
"passHostHeader": true
},
"status": "enabled",
"usedBy": [
"backend@docker"
],
"serverStatus": {
"http://172.23.0.2:5678": "UP"
}
}
}
}
And then did the test - and it is working for me as well.
$ curl -k -H Host:localhost https://127.0.0.1
Hostname: 6b5e6c192b5f
IP: 127.0.0.1
IP: 172.23.0.2
RemoteAddr: 172.23.0.3:52438
GET / HTTP/1.1
Host: localhost
User-Agent: curl/7.54.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.23.0.1
X-Forwarded-Host: localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 059c9f8e8d3b
X-Real-Ip: 172.23.0.1
I then verified the previous docker compose file to be working, too.
While that's good I hate not knowing the why:
Maybe a faulty network connection between traefik and the backend container resulted in the 404? But that should have given a different error message, no?
Maybe just a docker restart would have fixed it, too?
Maybe the docker update fixed it?
How frustrating to not know.
tcurdt
November 3, 2019, 1:34am
17
Interesting - I am back to the 404. Investigating further.
ldez
November 3, 2019, 1:39am
18
I recommend to do:
$ docker-compose down
$ docker-compose up --remove-orphans
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
235cbded33e2 traefik:2.0.4 "/entrypoint.sh --en…" 27 minutes ago Up 27 minutes 0.0.0.0:443->443/tcp, 80/tcp, 0.0.0.0:8080->8080/tcp tem_web_1
cea44e30ae28 containous/whoami "/whoami --port=5678" About an hour ago Up 27 minutes 80/tcp tem_backend_1
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
227b4abb185b bridge bridge local
9b62799d98ec host host local
d3326558f216 none null local
729231fd556a tem_default bridge local
tcurdt
November 3, 2019, 1:06pm
19
OK - so I think I was just too tired last night and forget to set the Host
header. So I think the initial 404 was docker glitch and we cannot find the actual cause at this stage anymore.
That said - it would be super cool if traefik could (at least in DEBUG) tell when there is no match for the given host. And not just return a 404 without leaving any clue. That would be my request for improvement.