# Enabling a middleware for all Hosts matching a Regexp

**URL:** <https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164>\
**Category:** Traefik v3 (latest)\
**Tags:** docker, middleware\
**Created:** [January 21, 2025, 10:08am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164 "2025-01-21T10:08:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![sgw](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@sgw](https://community.traefik.io/u/sgw)\
**Post date:** [January 21, 2025, 10:08am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/1 "2025-01-21T10:08:22Z")

</div>

I prepare a docker-compose-stack with traefik to proxy http(s) to various docker containers.

I use ACME/LetsEncrypt-Certs also. Things work so far.

Now we want to write a general rule saying:

"every Host matching dev.\*.ci.tld.com should only be reachable from a specific ipallowlist"

I searched the web etc and already know that I should set up a router like:

```auto
http:
  routers:
    router-v3:
      entryPoints:
        - websecure
      rule: HostRegexp(dev\\.`[a-z]+\\.ci\\.tld\\.com`)
      ruleSyntax: v3
      middleware: ipallowlist2

```

Right?

I try to add that to the dynamic config of my container.  
Is that correct?

Basically there are these 2 files (host-paths, files are mounted into `/etc/traefik` inside the container:

```auto
# cat traefik/config/traefik.yml 
api:
  dashboard: true
  insecure: true
  
  
entryPoints:
  ping:
    address: ':88'
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"
    http:
      # middlewares:
      # - traefik-crowdsec-bouncer@file
    proxyProtocol:
      trustedIPs:
       - 10.0.0.0/8
       - 172.16.0.0/12
       - 192.168.0.0/16
       - 62.40.xxx.yyy
    forwardedHeaders:
      trustedIPs:
       - 10.0.0.0/8
       - 172.16.0.0/12
       - 192.168.0.0/16
       - 62.40.xxx.yyy
  grafana:
    address: ":3000"
  grafana-secure:
    address: ":3001"
  portainer:
    address: ":9000"
  portainer-secure:
    address: ":9001"
  prometheus:
    address: ":9090"
  prometheus-secure:
    address: ":9091"
   
ping:
  entryPoint: "ping"
    
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: "nextcloud_proxy"
  file:
    directory: "./"
    watch: true
    
    
certificatesResolvers:
  http_resolver:
    acme:
      email: "administrator@tld.com"
      storage: "acme.json"
      httpChallenge:
        entryPoint: web
          # caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
  tls_resolver:
    acme:
      email: "administrator@tld.com"
      storage: "tls_letsencrypt.json"
      tlsChallenge: {} 
        
log:
  level: DEBUG

metrics:
  prometheus:
    addRoutersLabels: true
    buckets: "0.1,0.3,1.2,5.0"
  
accessLog: {}

```

(I know: one TLS-resolver is too much ... other topic)

and

```auto
# cat traefik/config/dynamic_conf.yml 
tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true
http:
  #routers:
  # router-v3:
  # entryPoints:
  # - websecure
  # rule: HostRegexp(dev\\.`[a-z]+\\.ci\\.tld\\.com`)
  # ruleSyntax: v3
  # middleware: ipallowlist2
  middlewares:
    default:
      chain:
        middlewares:
          - default-security-headers
          - test-ipallowlist
            #- gzip
            #- test-ratelimit

    default-security-headers:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        frameDeny: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000
        customFrameOptionsValue: "SAMEORIGIN"

    nextcloud-headers:
      headers:
        browserXssFilter: true # X-XSS-Protection=1; mode=block
        contentTypeNosniff: true # X-Content-Type-Options=nosniff
        forceSTSHeader: true # Add the Strict-Transport-Security header even when the connection is HTTP
        frameDeny: true # X-Frame-Options=deny
        referrerPolicy: "strict-origin-when-cross-origin"
        stsIncludeSubdomains: true # Add includeSubdomains to the Strict-Transport-Security header
        stsPreload: true # Add preload flag appended to the Strict-Transport-Security header
        stsSeconds: 63072000 # Set the max-age of the Strict-Transport-Security header (63072000 = 2 years)
        customFrameOptionsValue: "SAMEORIGIN"

    gzip:
      compress: {}

    real-ip-cf:
      plugin:
        real-ip:
          Proxy:
            - proxyHeadername: "*"
              realIP: Cf-Connecting-Ip
              OverwriteXFF: true

    test-ipallowlist:
      ipAllowList:
        sourceRange:
[MASKED]

    ipallowlist2:
      ipAllowList:
        sourceRange:
[MASKED]

    test-ratelimit:
      rateLimit:
        average: 100
        burst: 50

```

Is the spot in the dynamic config the right place to work from?  
If I uncomment the block traefik dashboard fails ... I still have to dig through all the logs to maybe spot the issue, sorry.

I just ask for a general direction here: where to place that rule, how to name/configure that router etc

thanks in advance!

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [January 21, 2025, 12:02pm UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/2 "2025-01-21T12:02:14Z")

</div>

You can assign a `middleware` to an `entrypoint` or `router`. Router will use `rule` to match incoming requests. As you stated, you can use a Regex on the router rule, but you can only assign a single target `service` to the router.

---

<div class="post-metadata">

**Author:** ![sgw](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@sgw](https://community.traefik.io/u/sgw)\
**Post date:** [January 22, 2025, 7:05am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/3 "2025-01-22T07:05:42Z")

</div>

Thank you! So in my case this would go into `traefik.yml`, into the part defining the entrypoint `websecure`? I still don't understand how to place the rule with the HostRegexp there. Could you advise?

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [January 22, 2025, 9:00am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/4 "2025-01-22T09:00:44Z")

</div>

No, `routers` are defined in dynamic config.

You can assign a `middleware` to an `entrypoint` (listening port) for all `routers` using it ([doc](https://doc.traefik.io/traefik/routing/entrypoints/#middlewares)).

Note: you can’t really assign a global `middleware` to something like \*.local.example.com (using multiple routers), if that is what you are looking for.

---

<div class="post-metadata">

**Author:** ![sgw](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@sgw](https://community.traefik.io/u/sgw)\
**Post date:** [January 22, 2025, 11:20am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/5 "2025-01-22T11:20:13Z")

</div>

If I assign a `middleware` to an `entrypoint` can it still use that filtering via a `HostRegexp` rule?  
thank you, sorry for being slow ..

---

<div class="post-metadata">

**Author:** ![bluepuma77](https://avatars.discourse-cdn.com/v4/letter/b/a9adbd/32.png) [@bluepuma77](https://community.traefik.io/u/bluepuma77)\
**Post date:** [January 22, 2025, 11:32am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/6 "2025-01-22T11:32:11Z")

</div>

If you assign the `middleware` to the `entrypoint`, then it will be applied to all routers using that entrypoint.

If you want a middleware to be assigned to a single router/service, then you should assign it to the router only.

If you have those on websecure entrypoint

```auto
www.example.com -> www target service
a.ci.example.com -> a target service
b.ci.example.com -> b target service (different than a)

```

then you need to create multiple routers for each ci with different target and assign middleware to every single one. (Maybe I am just too complicated 😉)

---

<div class="post-metadata">

**Author:** ![sgw](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@sgw](https://community.traefik.io/u/sgw)\
**Post date:** [January 29, 2025, 10:57am UTC](https://community.traefik.io/t/enabling-a-middleware-for-all-hosts-matching-a-regexp/26164/7 "2025-01-29T10:57:54Z")

</div>

Drifted off here, other topics. I think I will stay with labels in docker-compose. Thanks so far!
