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

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)¶

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 - 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])

docker swarm custom containers with traefik

I'm trying to set up a docker swarm using traefik in digital ocean. I followed this tutorial and I get it to work entirely until I add one of my custom made containers. I am trying to simply add one first (there are 14 in total) and they are all very very similar, all of them are express apps that serve as restful API's handling one resource per service. However, when trying to access that specific subdomain I get a connection refused error.
Here's my docker-stack.yml file:
version: '3.6'
services:
traefik:
image: traefik:latest
networks:
- mynet
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
ports:
- "80:80"
- "8080:8080"
command: --api
main:
image: nginx
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=main"
- "traefik.frontend.rule=Host:domain.com"
two:
image: jwilder/whoami
networks:
- mynet
deploy:
labels:
- "traefik.port=8000"
- "traefik.backend=two"
- "traefik.frontend.rule=Host:two.domain.com"
three:
image: emilevauge/whoami
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=three"
- "traefik.frontend.rule=Host:three.domain.com"
user-service:
image: hollarves/users:latest
env_file:
- .env.user
networks:
- mynet
deploy:
labels:
- "traefik.port=80"
- "traefik.backend=users"
- "traefik.frontend.rule=Host:users.domain.com"
networks:
mynet:
driver: overlay
As I said, going to two.domain.com and three.domain.com works fine, and the whoami containers respond with their info. However, I get a connection refused error when trying users.domain.com
Note: domain.com is an actual domain I am using that is live pointing to a digitalocean cluster, I'm just hiding it for privacy reasons.
The entrypoint for this users-service is:
if (process.env.NODE_ENV !== "production") {
require("dotenv").load()
}
const express = require("express"),
bodyParser = require("body-parser"),
logger = require("morgan"),
//helmet = require("helmet"),
cors = require("cors"),
PORT = parseInt(process.env.PORT, 10) || 80
const server = express(),
routes = require("./server/routes")
//server.use(helmet())
server.use(cors())
server.use(logger("dev"))
server.use(bodyParser.json())
server.use("/", routes)
/*eslint no-console: ["error", { allow: ["log"] }] */
const serverObj = server.listen(PORT, () => { console.log("Server listening in PORT ", PORT) })
module.exports = serverObj
I can also confirm that this service is listening on PORT 80 as that's what it outputs when fetching logs from it using docker service logs test-stack_user-service:
test-stack_user-service.1.35p3lxzovphr#node-2 | > users-mueve#0.0.1 start /usr/src/app
test-stack_user-service.1.35p3lxzovphr#node-2 | > node server.js
test-stack_user-service.1.35p3lxzovphr#node-2 |
test-stack_user-service.1.35p3lxzovphr#node-2 | Server listening in PORT 80
Here is my traefik.toml config file just in case:
debug = true
logLevel = "DEBUG"
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[retry]
[docker]
endpoint="unix:///var/run/docker.sock"
exposedByDefault=true
watch=true
swarmmode=true
I can also see the containers in the traefik dashboard like I used to in my local environment.
I feel like I'm missing a very small detail that is preventing my service from working correctly. Any pointers will be extremely appreciated.
Thanks!

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

How to add proper labels in docker for 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