Dear All,
I'm new to Traefik, and have done a lot of reading before attempting to install it for my VPS. Now I am at a stage where all the services that I need are exposed. However, I cannot get the main domain to redirect (anywhere). I would like to redirect it to another site.
In the DEBUG log I can see, that all the subdomains are getting SSL certificates (if they need), but if I visit
mydomain.com
or
www.mydomain.com
I get a similar error:
time="2023-07-18T17:58:29+03:00" level=debug msg="Serving default certificate for request: \"www.mydomain.com\""
time="2023-07-18T17:58:29+03:00" level=debug msg="http: TLS handshake error from 172.68.62.27:56516: remote error: tls: unknown certificate authority"
My server is behind Cloudflare, but I don't think that is an issue as all the subdomains work correctly.
This is my docker-compose.yml
:
version: "3"
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
networks:
- mynet
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
- ./data:/etc/traefik
- ./ssl-certs:/ssl-certs
- ./logs:/var/log/traefik
labels:
- traefik.enable=true
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.rule=Host(`traefik.mydomain.com`)
- traefik.http.routers.traefik.tls=true
- traefik.http.routers.traefik.tls.certresolver=production
- traefik.http.services.traefik.loadbalancer.server.port=8080
- traefik.http.routers.catchall.entrypoints=websecure
- traefik.http.routers.catchall.rule=HostRegexp(`{host:.+}`)
- traefik.http.routers.catchall.priority=1
- traefik.http.routers.catchall.tls.certresolver=myresolver
- traefik.http.services.catchall.loadbalancer.server.port=80
- traefik.http.routers.catchall.middlewares=redirectall
- traefik.http.middlewares.redirectall.redirectregex.regex=.*
- traefik.http.middlewares.redirectall.redirectregex.replacement=https://anotherdomain.com
networks:
mynet:
external: true
Finally, here is my traefik.yml
:
global:
checkNewVersion: true
level: DEBUG
format: common
filePath: /var/log/traefik/traefik.log
dashboard: false
insecure: false
entryPoints:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: :443
certificatesResolvers:
staging:
acme:
email: [email protected]
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
httpChallenge:
entryPoint: web
production:
acme:
email: [email protected]
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
httpChallenge:
entryPoint: web
providers:
docker:
exposedByDefault: false
file:
directory: /etc/traefik/configuration
watch: true
What am I missing?
I'm afraid I don't quite understand what you mean. I had a look at the example you have shown (in fact, I had been experimenting with it before), and while it works as it is (well, I added tls
to it), it didn't get me any closer to the solution.
Entering whoami.mydomain.com
works fine, but www.whoami.mydomain.com
fails with the following error in the browser (Brave, incognito mode):
This site can’t provide a secure connection www.whoami.mydomain.com uses an unsupported protocol.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Also, what do you mean by:
You could use HostSNI(
*)
for websecure catchall rule.
I like the idea of a catchall rule... but where do I put it?
<thanks for sticking with me on this issue!>
I managed to redirect the main domain like this:
# Redirecting main domain
- "traefik.http.routers.domain.entrypoints=websecure"
- "traefik.http.routers.domain.rule=Host(`mydomain.com`)"
- "traefik.http.routers.domain.tls.certresolver=production"
- "traefik.http.routers.domain.middlewares=domain"
- 'traefik.http.middlewares.domain.redirectregex.regex=^https://mydomain.com/(.*)'
- 'traefik.http.middlewares.domain.redirectregex.replacement=https://google.com/$${1}'
- "traefik.http.middlewares.domain.redirectregex.permanent=false"
This is now working as expected. Is this the preferred way to do it, though?
Also, this only redirects the main domain, but not all the "non-existing" subdomains.
Traefik uses a router
to match a route, then applies middleware
, to finally forward via service
.
traefik.http.routers.domain.rule=HostSNI(`*`)
is a catchall for https/TLS connections.
This requires that you use a wildcard cert, so that Traefik knows what domains to get a cert for, and also that browsers will not show "invalid cert".
And you need to update your current RegEx to match any domain.
As I stated before
This requires that you use a wildcard cert, so that Traefik knows what domains to get a cert for, and also that browsers will not show "invalid cert".
Either you specify all used domains with Host() || Host() || ...
or you use a wildcard cert, either by buying one or using LetsEncrypt with dnsChallnge (doc).
I've been trying to get this working all day long, with no luck.
I have now this in my traefik.yml
:
certificatesResolvers:
production:
acme:
email: [email protected]
storage: /etc/traefik/certs/acme.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 0
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
and this in docker-compose.yml
:
- traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)
- traefik.http.routers.http_catchall.entrypoints=web,websecure
- traefik.http.routers.http_catchall.middlewares=default_host
- traefik.http.middlewares.default_host.redirectregex.regex=^https://(.*)?mydomain.com(.*)$$
- traefik.http.middlewares.default_host.redirectregex.replacement=https://google.com
- traefik.http.middlewares.default_host.redirectregex.permanent=false
- traefik.http.routers.wildcard.tls=true
- traefik.http.routers.wildcard.tls.certresolver=production
- traefik.http.routers.wildcard.tls.domains[0].main=mydomain.com
- traefik.http.routers.wildcard.tls.domains[0].sans=*.mydomain.com
Still, no luck. All the subdomains defined work well, the main domain redirects correctly as well. But an undefined subdomain, like blah.mydomain.com
gives me a 404 page not found
error.
In the logs I can't see any error:
time="2023-07-19T18:04:20+03:00" level=info msg="Traefik version 2.10.3 built on 2023-06-19T16:18:54Z"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider aggregator aggregator.ProviderAggregator"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *file.Provider"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *traefik.Provider"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *docker.Provider"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *acme.ChallengeTLSALPN"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *acme.Provider"
time="2023-07-19T18:04:20+03:00" level=info msg="Testing certificate renew..." providerName=production.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
time="2023-07-19T18:04:20+03:00" level=info msg="Starting provider *acme.Provider"
time="2023-07-19T18:04:20+03:00" level=info msg="Testing certificate renew..." providerName=staging.acme ACME CA="https://acme-staging-v02.api.letsencrypt.org/directory"
Routers need a rule to be matched, routers.wildcard
probably does nothing.
Assign your certresolver to websecure entrypoint.
See simple Traefik example.
So I changed my config like this, I even put in priority
:
- traefik.http.routers.http_catchall.priority=999999
- traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)
- traefik.http.routers.http_catchall.entrypoints=websecure
- traefik.http.routers.http_catchall.middlewares=default_host
- traefik.http.middlewares.default_host.redirectregex.regex=^https://(.*)?mydomain.com(.*)$$
- traefik.http.middlewares.default_host.redirectregex.replacement=https://google.com
- traefik.http.middlewares.default_host.redirectregex.permanent=false
- traefik.http.routers.http_catchall.tls=true
- traefik.http.routers.http_catchall.tls.certresolver=production
- traefik.http.routers.http_catchall.tls.domains[0].main=mydomain.com
- traefik.http.routers.http_catchall.tls.domains[0].sans=*.mydomain.com
Now I am getting Too many redirects
in the browser, for any request.
After a lot more research, I am finally starting to begin to understand how Traefik works.
I managed to get the desired behavior with the following setup:
I removed all shenanigans from docker-compose.yml
, and added the following to the dynamic config:
routers:
domainRouter:
entrypoints:
- websecure
rule: "Host(`mydomain.com`)"
service: dummy
middlewares:
- domain
certresolver: production
catchAllRouter:
entrypoints:
- websecure
middlewares:
- catchAll
rule: "PathPrefix(`/`)"
service: dummy
priority: 1
certresolver: production
domains:
- main: "mydomain.com"
- sans: "*.mydomain.com"
middlewares:
domain:
redirectregex:
regex: "^https://mydomain.com/(.*)"
replacement: "https://mydomain.com/${1}"
permanent: true
catchAll:
redirectregex:
regex: "^.*$"
replacement: "https://mydomain.com/${1}"
permanent: false
This accomplishes the following:
The main domain is redirected to a custom URL
Any subdomain that is not explicitly defined in docker label rules get redirected to another custom domain.
@bluepuma77 thank you for nudging me in the right direction!