How to add proper labels in docker for SSL? - ssl

I have managed to setup Traefik to to work with my docker swarm and for HTTP requests it works great. However, I don't know how to setup SSL for some of my containers. I will be using letsencrypt for generating certificates.
traefik.toml (partial)
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "acme#example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
caServer = "https://acme-staging.api.letsencrypt.org/directory"
docker-compose.yml
version: '3'
services:
web:
...
deploy:
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=Host:example.com,www.example.com"
- "traefik.docker.network=public"
- "traefik.frontend.entryPoints=http"
- "traefik.backend=service_web"
In this configuration, my application never reaches SSL because my containers do not have SSL entryPoint setup. If I change "traefik.frontend.entryPoints" to "https", Letsencrypt gets called (LE givges error because of staging but that doesn't matter to me at this moment).
My biggest problem is that, I still don't know how to convert traefik TOML config into docker-compose labels. For example, Traefik docs explain entrypoints but I have bunch of services that live under different domains. Some have SSL, some do not have SSL; therefore, I want to be able to set up both http and https entryPoints, http to https redirects etc. using only docker-compose.
Also, once I am able to set entrypoints in docker-compose, do I need to keep the [entryPoints] block in traefik.toml?

Ahoi!
Requirements: Local-Persist Volume Plugin:
https://github.com/CWSpear/local-persist (otherwise the Volume Driver has to be changed)
The Network for Traefik has to be pre-created: "docker network create proxy -d overlay"
(1) Fire Up Traefik:
version: "3"
services:
traefik:
image: traefik
#command: --consul --consul.endpoint=consul:8500
#command: storeconfig --consul --consul.endpoint=consul:8500
networks:
- proxy
ports:
- 80:80
- 443:443
#- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefikdata:/etc/traefik/
deploy:
#replicas: 3
replicas: 1
placement:
constraints: [node.role == manager]
update_config:
parallelism: 1
delay: 45s
monitor: 15s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 10
window: 60s
volumes:
traefikdata:
driver: local-persist
driver_opts:
mountpoint: /data/docker/proxy
networks:
proxy:
external: true
Important Note: When using ACME and you'd like to scale the Traefik (like here 3), you have to use Consul or ETCD as a "storage" for the Config.
You do not use Consule or ETCD if you just use one Instance of Traefik.
With a normal Certificate ETCD & Consul is never required.
(2) Mount traefik.toml
logLevel = "WARN"
debug = false
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
compress = false
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
#Letsencrypt
[acme]
email = "admin#berndklaus.at"
storage = "traefik/acme/account"
entryPoint = "https"
onHostRule = true
onDemand = true
#[[acme.domains]]
# main = "yourdomain.at"
# sans = ["sub1.yourdomain.at", "www.yourdomain.at"]
#[[acme.domains]]
# main = "anotherdomain.at"
#[web]
#address = ":8080"
[docker]
domain = "docker.localhost"
watch = true
swarmmode = true
The uncommented Part is not mandatory
(3) Start any Service
version: '3'
services:
nginx:
image: nginx
deploy:
labels:
- "traefik.port=80"
- "traefik.docker.network=proxy"
- "traefik.frontend.rule=Host:sub1.yourdomain.at"
- "traefik.backend=nginx"
- "traefik.frontend.entryPoints=http,https"
replicas: 1
networks:
proxy:
aliases:
- nginx
volumes:
- html:/usr/share/nginx/html
environment:
- NGINX_HOST=sub.yourdomain.at
- NGINX_PORT=80
#command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
networks:
proxy:
external: true
default:
driver: overlay
volumes:
html:
driver: local-persist
driver_opts:
mountpoint: /data/docker/html
Some more examples: https://github.com/Berndinox/compose-v3-collection

Related

Localtunnel with Traefik and ssh

I'm looking for a solution with Traefik to do my own Ngrok alternative.
I have multiple a home assistant with the Autossh plugin installed on an another server and would like to access to it by entered the url : home-assistant.server.com
Authssh is configured with the remote forwarding port : 44400:localhost:8123, on ssh port (22).
I found this Traefik configuration (Traefik V1) but would like to use Traefik V2.
I obtain a Bad gateway with my new Traefik configuration.
Do you have any idea to resolve it ? Thanks.
Here, my Traefik V2 configuration :
traefik.toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[api]
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
[providers.file]
filename = "/etc/traefik/services.toml"
[certificatesResolvers.mycertificate.acme]
email = "contact#server.com"
storage = "acme.json"
[certificatesResolvers.mycertificate.acme.httpChallenge]
entryPoint = "http"
services.toml
[http]
[http.services]
[http.services.nas]
[http.services.nas.loadBalancer]
[[http.services.nas.loadBalancer.servers]]
url = "http://localhost:44400"
docker-compose.yml
version: '3.7'
services:
reverse-proxy:
restart: always
image: traefik:chevrotin
ports:
- "443:443"
- "80:80"
volumes:
- /srv/traefik.toml:/etc/traefik/traefik.toml
- /srv/services.toml:/etc/traefik/services.toml
- /var/run/docker.sock:/var/run/docker.sock
- /srv/acme.json:/acme.json
labels:
- traefik.http.routers.nas.entrypoints=https
- traefik.http.routers.nas.rule=Host(`home-assistant.server.com`)
- traefik.http.routers.nas.service=nas#file
- traefik.http.routers.nas.tls=true
- traefik.http.routers.nas.tls.certresolver=mycertificate

Traefik 2.0: How to configure `traefik.frontend.rule=Host:example.com`?

I just attempted to upgrade my existing pretty simple Traefik setup to 2.0.
I am using Docker as a provider.
I am running the containers with docker-compose. This is my docker-compose config:
version: "3.5"
services:
traefik:
image: traefik:v2.0-alpine
read_only: yes
ports:
- 80:80
- 443:443
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
- type: bind
source: ./traefik.toml
target: /traefik.toml
- type: bind
source: ./acme.json
target: /acme.json
networks:
- traefik
example:
image: example.com/example/example
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=Host:example.com"
- "traefik.docker.network=traefik"
networks:
- traefik
This is my traefik.toml:
defaultEntryPoints = ["http", "https"]
[Global]
sendAnonymousUsage = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "ssl#example.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
onDemand = false
acmeLogging = true
[acme.tlsChallenge]
[docker]
exposedByDefault = false
This setup works fine with Traefik 1.7.
With Traefik 2.0 I observe two issues, looking at the ACME log:
Unable to obtain ACME certificate for domains traefik-example-deployment
Unable to obtain ACME certificate for domains example-example-deployment
Traefik is apparently exposing both containers. It should only expose the example container.
Traefik is ignoring the traefik.frontend.rule=Host:example.com label.
I suspect this might be due to configuration format changes in Traefik 2.0. However, although I looked through the 2.0 documentation, I was unable how the correct configuration looks.
Routers¶
To update the configuration of the Router automatically attached to the container, add labels starting with traefik.routers.{name-of-your-choice}. and followed by the option you want to change. For example, to change the rule, you could add the label traefik.http.routers.my-container.rule=Host(my-domain).
Every Router parameter can be updated this way.
As Mentioned in Doc - https://docs.traefik.io/v2.0/providers/docker/
change the labels: to
services:
my-container:
# ...
labels:
- traefik.http.routers.my-container.rule=Host(`my-domain`)
To tell Traefik not to expose Container - add - traefik.enable=false
As traefik Expose containers by default through Traefik. If set to false, containers that don't have a traefik.enable=true label will be ignored from the resulting routing configuration.
exposedByDefault (Optional, Default=true)¶

Traefik - cannot show dashboard

Treafik redirecting works like charm!
How can I configure the Traefik dashboard to be shown?
I have an "A"-record pointing to my domain and a CNAME record "monitor" pointing to the same domain. Is this correct?
My first attempt was this docker-compose.yml file. It contains also a Spring Boot application listening at 8080:
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
command: --api --docker
restart: always
networks:
- geosolutionsnet
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ec2-user/traefik/traefik.toml:/traefik.toml
- /home/ec2-user/traefik/acme.json:/acme.json
ports:
- "80:80"
- "443:443"
labels:
- "traefik.docker.network=geosolutionsnet"
- "traefik.enable=true"
- "traefik.frontend.rule=Host:monitor.xyz.nl"
- "traefik.port=8080"
- "traefik.protocol=http"
#- "traefik.frontend.headers.STSSeconds=15768000"
With the browser I pointed to 'monitor.xyz.nl' but I got a 404.
My second try was with:
- "traefik.frontend.rule=Host:xyz.nl;Path:/monitor"
Pointing my browser to xyz.nl/monitor ... gave again a 404.
My traefik.toml file is:
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "xyz.nl"
watch = true
exposedByDefault = false
[acme]
email = "jj#xyz.nl"
storage = "acme.json"
onHostRule = true
entryPoint = "https"
onDemand = false
[acme.tlsChallenge]
UPDATE:
Using the CNAME traefik that is mapped to domain xyz.nl/traefik results in a 404 error.
Using the CNAME 'monitor' pointing to the (A-record) domain I get the same result. I think that is normal because I configured the host match via a pathprefix.
In the Docker compose I added to the traefik part port 8080:8080.
Then, the Traefik dashboard was shown by navigating to port 8080. Important is to navigate via 'http' and NOT 'https'.
The next improvement is by using HTTPS so that no unfriendly people can visit the Traefik dashboard.
docker-compose.yml
services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
networks:
- geosolutionsnet
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/ec2-user/traefik/traefik.toml:/traefik.toml
- /home/ec2-user/traefik/acme.json:/acme.json
ports:
- "80:80"
- "443:443"
labels:
- "traefik.docker.network=geosolutionsnet"
- "traefik.enable=true"
- "traefik.frontend.rule=Host:xyz.nl;PathPrefix:/monitor" # <----
- "traefik.port=8080"
treafik.toml
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[api]
[docker]
domain = "xyz.nl"
exposedByDefault = false
[acme]
email = "jj#xyz.nl"
storage = "acme.json"
onHostRule = true
entryPoint = "https"
onDemand = false
[acme.tlsChallenge]
I recommend to not mix CLI args and TOML for the same section (ex: --docker and [docker])

Redirect HTTP to HTTPS on localhost

I want to have a dev setup on my local machine to more easily test new versions of my programm - it's a server/client application. The client does need SSL and so I want to have traefik as a proxy to the (local) server which will use a self signed certificate.
I managed to get a connection without SSL but as soon as I enable HTTPS / Redirecting, traefik only responses with "backend not found" "/" 0ms.
The SSL certificate is valid according to my browsers.
Here is my setup:
traefik.toml
[docker]
watch = true
exposedByDefault = false
logLevel = "DEBUG"
defaultEntryPoints = ["https", "http"]
[accessLog]
[traefikLog]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
ca = "etc/traefik/ca.cert.pem"
certFile = "/etc/traefik/dev-cert.pem"
keyFile = "/etc/traefik/dev-key.nopass.pem"
# API definition
[api]
entryPoint = "traefik"
dashboard = true
docker-compose.yaml
version: '3'
services:
edv-reverse-proxy:
image: traefik
container_name: edv-reverse-proxy
expose:
- 8080
ports:
- 80:80
- 443:443
- 8080:8080
volumes:
- ./traefik/dev-cert.pem:/etc/traefik/dev-cert.pem
- ./traefik/dev-key.nopass.pem:/etc/traefik/dev-key.nopass.pem
- ./traefik/ca.cert.pem:/etc/traefik/ca.cert.pem
- ./traefik/traefik.toml:/etc/traefik/traefik.toml
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
whoami:
image: emilevauge/whoami
expose:
- 80
labels:
- traefik.enable=true
- "traefik.frontend.rule=Host:whoami.test"
- traefik.port=80
networks:
- proxy
networks:
proxy:
external: true
/etc/hosts
127.0.0.1 whoami.test
If I disable the whole entrypoints section I can connect to the service with whoami.test like expected. I tried a lot of different settings which didn't seem to have any effect.
So if anyone knows how to solve this I would be really glad!
Fields order is important in toml:
logLevel = "DEBUG" # <---
defaultEntryPoints = ["https", "http"] # <---
[accessLog]
[traefikLog]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
ca = "etc/traefik/ca.cert.pem"
certFile = "/etc/traefik/dev-cert.pem"
keyFile = "/etc/traefik/dev-key.nopass.pem"
# API definition
[api]
entryPoint = "traefik"
dashboard = true
[docker]
watch = true
exposedByDefault = false
For a traefik v2.1 default router http to https redirect you can do the following:
traefik:
image: traefik:v2.1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- 80:80
- 443:443
labels:
- "traefik.enable=true"
### Default HTTP Router
- "traefik.http.routers.default-http2https.rule=HostRegexp(`{subdomain:[a-z,0-9]+}.example.com`)"
- "traefik.http.routers.default-http2https.entrypoints=http"
- "traefik.http.routers.default-http2https.middlewares=https-redirect#file"
### SSL
- "traefik.http.routers.frontend.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.frontend.entrypoints=https"
- "traefik.http.routers.frontend.tls.certresolver=example.com"
- "traefik.http.routers.frontend.tls.domains[0].main=example.com"
- "traefik.http.routers.frontend.tls.domains[0].sans=*.example.com"
- "traefik.http.routers.frontend.service=api#internal"
I found the solution here: https://docs.traefik.io/routing/routers/#rule

ACME http2 server error with Traefik

I am not sure this is a bug but I have laterally scoured every thread for the past 3 days and I am at my wits end.
I am unable to get ACME working with Traefik in swarm mode.
docker-compose.yml
version: "3.4"
services:
consul:
image: consul
command: agent -server -client='{{ GetInterfaceIP "eth0" }}' -bind='{{ GetInterfaceIP "eth0" }}' -bootstrap
networks:
- consul
volumes:
- "/srv/www/consul:/data"
deploy:
mode: global
placement:
constraints: [node.role == manager]
update_config:
parallelism: 1
delay: 45s
monitor: 15s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 10
window: 60s
traefik:
image: traefik:1.5.4
command: -c --web --logLevel=DEBUG --debug=true
deploy:
mode: global
restart_policy:
condition: on-failure
update_config:
parallelism: 1
delay: 10s
placement:
constraints:
- node.role == manager
networks:
- traefik_net
- consul
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /srv/www/certs:/certs/
- /srv/www/docker/traefik.toml:/traefik.toml
traefik.toml
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[docker]
watch = true
swarmmode = true
[consul]
endpoint = "consul:8500"
prefix = "traefik"
[acme]
email = "myemail#domain.com"
storage = "traefik/acme/account"
entryPoint = "https"
onDemand = false
OnHostRule = true
acmeLogging = true
The network was created like.
docker network create --driver overlay --subnet 10.1.1.0/16 traefik_net
docker network create --driver overlay consul
The errors I am getting:
level=debug msg="No provided certificate found for domains staging.example.net, get ACME certificate."
level=debug msg="Looking for an existing ACME challenge for staging.example.net..."
level=debug msg="No certificate found or generated for staging.example.net"
level=debug msg="http2: server: error reading preface from client 10.255.0.3:51514: read tcp 10.255.1.47:443->10.255.0.3:51514: read: connection reset by peer"
The thing I don't get is the ip's that are showing here are part of the ingress network.
"Containers": {
"4befecaed26dbe9667481b911a03bd6d33cfacfbc48f0a773da60bd82e88c063": {
"Name": "server_traefik.ibi1uendqffht27anh9109ozk.s87e5ykdm0s8mmmv5jjc0ps64",
"EndpointID": "377f484f6c038c31a04fc7b02e7cf94a013a8d83916d03b57f8a74463159c1ca",
"MacAddress": "02:42:0a:ff:01:2f",
"IPv4Address": "10.255.1.47/16",
"IPv6Address": ""
},
"ingress-sbox": {
"Name": "ingress-endpoint",
"EndpointID": "e83ae16d6be547f3d2141c4d48aec8e0b3a45b0de841e1e155073a5011cbbab9",
"MacAddress": "02:42:0a:ff:00:03",
"IPv4Address": "10.255.0.3/16",
"IPv6Address": ""
}
},
Any direction would be greatly appreciated.
You must configure the ACME challenge:
[acme]
email = "myemail#domain.com"
storage = "traefik/acme/account"
entryPoint = "https"
onDemand = false
OnHostRule = true
acmeLogging = true
[acme.httpChallenge] # <---
entryPoint = "http" # <---
https://docs.traefik.io/v1.5/configuration/acme/#acmehttpchallenge