Can defaultrule=Host co-exist with label based HostRegexp routes?

Hi,

I would like to have a very simple traefik config that would have a default route (which works fine) but also a fallback route incase any of the services are down or the subdomain is used for something else.
The issue is that with the config below Hostregexp takes prority over the defaultroute but I would like the exact opposite to happen. Is there some way to make the regexp shorter if that matter? Help appreciated.

version: "3.7"

services:

  tra:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    command:
      - "--api.dashboard=true"
      - "--ping=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=true" # no labels needed in our docker compose files
      - "--providers.docker.defaultrule=Host(`{{ index .Labels \"com.docker.compose.service\"}}.$domain`)" # service name = cname
      - "--entrypoints.web.address=:22280" # behind nginx until everything works
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.websecure.address=:22443"
      - "--entrypoints.websecure.http.tls.domains.main=$domain"
      - "--entrypoints.websecure.http.middlewares=test-auth" # test only
      - "--entrypoints.traefik.address=:22288" # no conflict for dashboard port
      - "--accesslog=true"
      - "--accesslog.filepath=/etc/traefik/access.log"
      - "--log.filePath=/etc/traefik/traefik.log"
      - "--log.level=INFO"
      - "--providers.file.filename=/etc/traefik/dynamic.yaml" # tls config and manual routes
      - "--providers.file.watch=true"
      - "--pilot.token=$pilot"
    labels:
      - "traefik.http.routers.api.service=api@internal" # dashboard service
      - "traefik.http.services.api-svc.loadbalancer.server.port=22288" # !!! without this, the dashboard will return 404
      - "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$oNcYrRwI$$0/NZI6oT2pwDzPMR8pkXW." # test only
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./:/etc/traefik"
    network_mode: host # traefik will get access to all host routing

  public:
    image: containous/whoami
    container_name: whoami
    restart: unless-stopped
    labels:
      - "traefik.http.routers.public.rule=HostRegexp(`{s:[a-z]+}.$domain`)"

Hi @odt,

Thanks for your interest in Traefik!

It seems that setting the router priority could solve your issue. Check-out the following documentation for more details.

Hope this helps!

Hi @kevinpollet! Thanks for the reply, traefik is great but the journey to replace a 10+ year and 1k+ line nginx setup is not easy :slight_smile:

The issue with adding a priority is as soon as one is added witha a label, the "fallback route" will give 404 instead of serving the websecure endpoint in the above config. Should more labels be added to the fallback service? (public)

- "traefik.http.routers.public.rule.priority=1000"

I think your fallback router should have the smallest priority. By doing that, your fallback router will always be evaluated lastly. The following config should work:

public:
    image: containous/whoami
    container_name: whoami
    restart: unless-stopped
    labels:
      - "traefik.http.routers.public.rule=HostRegexp(`{s:[a-z]+}.$domain`)"
      - "traefik.http.routers.public.rule.priority=1"

Does it make sense or am I missing something?

Hey, I tried different values, as soon as a priority number is added it seems to invalidate the rule or something else because all requests that are not matched by the defaultrule will get 404. It's easily replicatable with running the above compose and trying to go to public.$domain

I tried your example and everything is working fine on my side (I used the following docker-compose command: domain=local docker-compose up). The following example is simpler and works also fine on my side:

version: "3.7"
services:
  traefik:
    image: traefik:latest
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.defaultrule=Host(`{{ index .Labels \"com.docker.compose.service\"}}.local`)"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    ports:
      - "80:80"
      - "8080:8080"

  foo:
    image: traefik/whoami
    environment:
      - WHOAMI_NAME=foo

  public:
    image: traefik/whoami
    environment:
      - WHOAMI_NAME=public
    labels:
      - "traefik.http.routers.public.rule=HostRegexp(`{s:[a-z]+}.local`)"
      - "traefik.http.routers.public.priority=1"

The following command commands give the expected results:

❯ curl localhost:80 -H "Host: foo.local"
Name: foo
Hostname: 41f34093b8f5
IP: 127.0.0.1
IP: 172.21.0.4
RemoteAddr: 172.21.0.2:41928
GET / HTTP/1.1
Host: foo.local
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.21.0.1
X-Forwarded-Host: foo.local
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: e7cf904b0294
X-Real-Ip: 172.21.0.1

❯ curl localhost:80 -H "Host: bar.local"
Name: public
Hostname: a83f31f5acb3
IP: 127.0.0.1
IP: 172.21.0.3
RemoteAddr: 172.21.0.2:40832
GET / HTTP/1.1
Host: bar.local
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.21.0.1
X-Forwarded-Host: bar.local
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: e7cf904b0294
X-Real-Ip: 172.21.0.1

Are you sure that your example is not working with the priority?
Maybe the test request is not matching the HostRegexp rule?

1 Like

Thanks mate, you fixed the syntax error for me, :flushed:
"traefik.http.routers.public.rule.priority=1" !=
"traefik.http.routers.public.priority=1"

since the example in docs only had yaml/toml syntax I made a mistake in the label conversion

So far so good!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.