Traefik self-signed certificated wildcard subdomain in docker-compose - docker

I'm looking for a solution to let traefik generate a wildcard certificate for my services. In fact in local development I do have multiple services sharing the same domain and currently I have to accept the certificate for each one.
I have 2 subdomains front.domain.localhost and api.domain.localhost and I would like a single certificate for both.
Here is a demo docker-compose.yml:
version: '3'
services:
traefik:
image: traefik:2.5
command:
- --providers.docker
- --entryPoints.http.address=:80
- --entryPoints.http.http.redirections.entryPoint.to=https
- --entryPoints.http.http.redirections.entryPoint.scheme=https
- --entryPoints.https.address=:443
labels:
- traefik.enable=true
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
front:
image: traefik/whoami
labels:
- traefik.http.routers.front_router.rule=Host(`front.domain.localhost`)
- traefik.http.routers.front_router.entrypoints=https
- traefik.http.routers.front_router.tls=true
api:
image: traefik/whoami
labels:
- traefik.http.routers.api_router.rule=Host(`api.domain.localhost`)
- traefik.http.routers.api_router.entrypoints=https
- traefik.http.routers.api_router.tls=true
With this one I should accept 2 certificates (one for each subdomain).
I tried with various combination of main and sans as explained in https://doc.traefik.io/traefik/routing/routers/#domains without success.
How can I achieve this ?

Related

Allow both http and https with Traefik on Docker

I am using Traefik in my VPS to route the traffic to my websites, after hours of messing around with it I finally managed to get it working with https using Le's Encrypt.
Now, one thing that I need to do is be able to also access my website via plain http as this is a hobby project for older browsers and the only reason I added tls is because Firefox doesn't like my website without it.
The problem is that, with my current configuration, I can access my website via https normally but when I try it with plain http I get a 404 error.
Here's what my config on docker-compose looks like:
version: "3"
services:
traefik:
image: "traefik:v2.5"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.teeresolver.acme.tlschallenge=true"
- "--certificatesresolvers.teeresolver.acme.email=me#gmail.com"
- "--certificatesresolvers.teeresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- mywebsite
# [...]
mywebsite:
image: my-web-site/site
build:
context: ~/mywebsite-runner/_work/my-web-site-php/my-web-site-php
dockerfile: Dockerfile
volumes:
- ./tee-downloads:/var/www/build/downloads
- ./tee-contents:/var/www/build/contents
ports:
- "0.0.0.0:8001:80"
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.themywebsite.entrypoints=websecure,web"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
networks:
- mywebsite
networks:
mywebsite:
I have been searching for a solution for hours but the only things I can find on google are configs to redirect http to https, which I can't do.
Does anyone know how to do that?
Thanks in advance for the help.
In traefik , each router defines a set of policies to apply depending of rules and entrypoints.
If you want 2 policies, one for http and one for https, you need to define 2 traefik routers :
mywebsite:
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.entrypoints=websecure"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.httpwebsite.entrypoints=web"
- "traefik.http.routers.httpwebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
One called themywebsite
Another one called httpwebsite
As a result, you do not use a certresolver for httpwebsite router.

setup 2 domains in my docker-compose + nginx-proxy

I'm trying to configure 2 domains to run on the same VPS.
using nginx-proxy + letsencrypt + docker-compose
i have setup both my domains to point to my VPS
i want to run 2 different sites with blazor client-side. (as a start simple index.html is fine)
how will i move on from here?
my docker-compose.yaml file
version: '2'
services:
proxy:
image: jwilder/nginx-proxy
container_name: proxy
restart: unless-stopped
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- certs:/etc/nginx/certs:rw
- vhost.d:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
ports:
- "80:80"
- "443:443"
networks:
- "default"
- "proxy-tier"
proxy-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt
restart: unless-stopped
environment:
- NGINX_PROXY_CONTAINER=proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes_from:
- "proxy"
depends_on:
- "proxy"
networks:
- "default"
- "proxy-tier"
portainer:
image: portainer/portainer:latest
container_name: portainer
restart: always
environment:
- VIRTUAL_HOST=docker.DOMAIN.dk
- LETSENCRYPT_HOST=docker.DOMAIN.dk
- LETSENCRYPT_EMAIL=EMAIL#hotmail.com
volumes:
- ./portainer/:/data
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "9000:9000"
volumes:
certs:
vhost.d:
html:
networks:
proxy-tier:
How about changing to use it with an other software like Traffik?
Using traffik to proxy your traffic and handle your certificates of let's-encrypt. So you have one container who does it both and you can fire up as many docker container with traffik labels to route with tls certificate to new subdomains etc.
Full Smarthome Example:
https://www.smarthomebeginner.com/traefik-2-docker-tutorial/#3_Domain_Name
Traffik handle multiple domains: https://plexguide.com/threads/howto-configure-traefik-to-handle-multiple-domain-names.3420/
Or the traffik doc: https://docs.traefik.io/v2.2/routing/routers/#tls

Using wildcard certificates in Traefik v2 on Docker Swarm

I am using the following Docker Compose file to deploy Traefik on a swarm cluster.
version: "3.7"
services:
traefik:
image: traefik:v2.1
command:
- "--api.dashboard=true"
- "--accesslog=true"
- "--log.level=INFO"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=traefik-public"
- "--providers.file.watch=true"
- "--providers.file.filename=/file_provider.yml"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.dnsChallenge.provider=cloudflare"
- "--certificatesresolvers.letsencrypt.acme.dnsChallenge.delayBeforeCheck=15"
- "--certificatesresolvers.letsencrypt.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
- "--certificatesresolvers.letsencrypt.acme.email=user#domain.tld"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- 80:80
- 443:443
volumes:
- traefik-certificates:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
networks:
- traefik-public
environment:
- "CF_API_EMAIL=user#domain.tld"
- "CF_API_KEY=api-key"
deploy:
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=true"
- "traefik.docker.lbswarm=true"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https#docker"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.routers.api.tls.domains[0].main=*.domain.tld"
- "traefik.http.routers.api.tls.domains[0].sans=domain.tld"
- "traefik.http.routers.api.rule=Host(`management.domain.tld`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.api.service=api#internal"
- "traefik.http.services.api.loadbalancer.server.port=8080"
configs:
- file_provider.yml
volumes:
traefik-certificates:
configs:
file_provider.yml:
file: /home/access/docker/traefik-provider.yml
networks:
traefik-public:
external: true
At the moment, I have hit the rate limit on management.domain.tld and I instead want to use a wildcard certificate so there is less likelihood that I will run into a rate limit again. I have Traefik configured to generate the wildcard certificate which works, but there is still a rate-limiting error on management.domain.tld in the logs. Also, when I go to management.domain.tld in the browser, I get an invalid SSL/TLS error. How do I get Traefik to use the wildcard certificate instead of issuing a new certificate for every host rule?
Looks like you have done everything right. But there is a slight mistake in the config.
main is the Subject field for the certificate. Meaning the domain/sub-domain the certificate is being issued to.
sans is the Subject Alternate Names field for the certificate. Meaning alternative domain/sub-domain that the certificate is also valid for.
So, Instead of using:
version: "3.7"
services:
traefik:
image: traefik:v2.1
...
labels:
- "traefik.http.routers.api.tls.domains[0].main=*.domain.tld"
- "traefik.http.routers.api.tls.domains[0].sans=domain.tld"
...
You should use:
version: "3.7"
services:
traefik:
image: traefik:v2.1
...
labels:
- "traefik.http.routers.api.tls.domains[0].main=domain.tld"
- "traefik.http.routers.api.tls.domains[0].sans=*.domain.tld"
...

How to map specific port inside docker container when using traefik?

Here's my docker-compose.yml:
version: '3'
services:
website:
build: ./website
expose: [3000]
labels:
- "traefik.frontend.rule=Host:localhost"
blog:
build: ./blog
expose: [4000]
labels:
- "traefik.frontend.rule=Host:localhost;PathPrefix:/blog"
docs:
build: ./docs
expose: [3000]
labels:
- "traefik.frontend.rule=Host:localhost;PathPrefix:/docs"
proxy:
image: traefik
command: --api.insecure=true --providers.docker
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
webgateway:
driver: bridge
What I want is access three different node.js websites via different routes. But these three node.js websites actually expose different ports. Now my treafik is running. I can config via localhost:8080 But localhost localhost/blog and localhost/docs are all 404 page not found
P.S: I'm not sure whether port is the issue I should investigate, because changing one node.js service to port 80 doesn't solve the puzzle. And I saw on traefik dashboard the rule is Host(blog-dev)
PathPrefix:/blog
When you have this as a routing rule, traefix won't automatically remove the prefix when sending to the container.
So unless you have a route /blog inside your container you will get a 404.
So what you normally do is also add a middleware to strip this ->
https://docs.traefik.io/middlewares/stripprefix/
Also you appear not to be setting your rules based on your service.
So as an example for your first service blog,
try->
labels:
- "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)"
- "traefik.http.routers.blog.middlewares=strip-blog"
- "traefik.http.middlewares.strip-blog.stripprefix.prefixes=/blog"
And then do the same for your other routes, don't forget to replace routers.blog with routers.docs etc..
labels:
- traefik.http.services.<YOUR-SERVICE-NAME>.loadbalancer.server.port=9763
EG:
services:
wso:
image: "my-custom-wso-image"
volumes:
- .....
labels:
- "traefik.enable=true"
- "traefik.http.routers.wso.tls=true"
- "traefik.http.routers.wso.rule=Host(`my.nice.url`)"
- "traefik.http.services.wso.loadbalancer.server.port=9763" #<-----
Thanks to #Keith I found the solution
version: '3'
services:
website:
build: ./website
expose: [3000]
networks: # It's essential to specify the same network in every service
- webgateway
labels:
- "traefik.http.routers.website.rule=Host(`localhost`)" # Use the right format
- "traefik.port=3000" # Let traefik find the right port
blog:
build: ./blog
expose: [4000]
networks:
- webgateway
labels:
- "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)" # blog has a root as `/blog` so no need to strip otherwise too many redirects
- "traefik.port=4000"
docs:
build: ./docs
expose: [3000]
networks:
- webgateway
labels:
- "traefik.http.routers.docs.rule=Host(`localhost`) && PathPrefix(`/docs`)"
- "traefik.http.routers.docs.middlewares=strip-docs" # Necessary as Keith mentioned
- "traefik.http.middlewares.strip-docs.stripprefix.prefixes=/docs"
- "traefik.port=3000"
proxy:
image: traefik
command: --api.insecure=true --providers.docker
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
webgateway:
driver: bridge

Traefik recreat all ACME certificate at each restart

I'm currently configuring Traefik with Let's encrypt.
But I have an issue : Each time I restart the container, Traefik regenerate all certificate. Even those already in the acme.json file :(.
But my server do automatic restart sometimes. So, within a day, Let's encrypt does not want to give me more certificates.
Do any way exist to rsolve this issue ? :(
My docker-compose.yml file :
services:
traefik:
image: traefik:alpine
restart: always
container_name: traefik
networks:
- default
- traefik_proxy
ports:
- "80:80"
- "443:443"
- "8000:8080"
volumes:
# traefik configuration files
- ${TRAEFIK_CONTAINERS_CONFIG_DIR}/traefik.toml:/etc/traefik/traefik.toml
- ${TRAEFIK_CONTAINERS_CONFIG_DIR}/acme.json:/acme.json
- ${TRAEFIK_CONTAINERS_CONFIG_DIR}/log:/var/log/traefik/
- ${TRAEFIK_CONTAINERS_CONFIG_DIR}/shared:/shared/
# Docker
- /var/run/docker.sock:/var/run/docker.sock
# We have to link the authentification dir to use the differents .htpasswd
- ${AUTHENTIFICATION_FILES_DIRECTORY}:/htpasswd/
labels:
- "traefik.enable=true"
- "traefik.frontend.rule=Host:reverse.${DOMAIN_NAME}"
- "traefik.port=8080"
- "traefik.frontend.auth.basic.usersFile=${TRAEFIK_DEFAULT_AUTHENTIFICATION_FILE}"
- "traefik.tags=proxy"
- "traefik.docker.network=traefik_proxy"

Resources