添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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. :slight_smile:

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!