Use named matchers with caddy-ratelimit module

1. The problem I’m having:

Hi, I’m trying to implement rate limiting with caddy-ratelimit. When I try to use @api named matcher inside rate_limit match directive it doesn’t rate limits the paths, but when I directly add the paths, rate limiting works. I’ve also tried simply adding @api inside match. It doesn’t rate limit either.

2. Error messages and/or full log output:

No Logs

3. Caddy version:

v2.8.4

4. How I installed and ran Caddy:

a. System environment:

Docker

b. Command:

docker compose up -d

c. Service/unit/compose file:

services:
  caddy:
    container_name: caddy
    build:
      dockerfile_inline: |
        FROM caddy:2.8.4-builder AS builder
        RUN xcaddy build --with github.com/mholt/caddy-ratelimit
        FROM caddy:2.8.4
        COPY --from=builder /usr/bin/caddy /usr/bin/caddy
    restart: unless-stopped
    environment:
      DOMAIN: ${DOMAIN:?error}
      CADDY_AUTH_USERNAME: ${CADDY_AUTH_USERNAME?:error}
      CADDY_AUTH_PASSWORD: ${CADDY_AUTH_PASSWORD?:error}
    ports:
      - 80:80
      - 443:443
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./volumes/caddy/caddy_data:/data
      - ./volumes/caddy/caddy_config:/config

d. My complete Caddy config:

{$DOMAIN} {
        tls internal
        @api path /rest/v1/* /api*
        handle @api {
                rate_limit {
                        zone my_zone {
                                match {
                                        path @api
                                }
                                key {remote_host}
                                window 1m
                                events 20
                        }
                }

                reverse_proxy node-app:8000
        }

        handle {
                basic_auth {
                        {$CADDY_AUTH_USERNAME} {$CADDY_AUTH_PASSWORD}
                }

                reverse_proxy dashboard:3000
        }

        handle_errors 429 {
                respond "You're being rate limited"
        }
}

The path matcher takes a path, not another named matcher. This configuration matches a path of literally @api.

You see this clearly when you run caddy adapt -p and inspect the output. You’ll see this segment:

{
	"handler": "rate_limit",
	"rate_limits": {
		"my_zone": {
			"key": "{http.request.remote.host}",
			"match": [
				{
					"path": [
						"@api"
					]
				}
			],
			"max_events": 20,
			"window": 60000000000
		}
	}
}

I’m not aware of a way to re-use a named matcher an nesting inside rate_limit module. You’ll have to repeat yourself, I’m afraid.

1 Like

Hi thankyou for your reply. I went with the route directive. Adding it here if someone refers to this post later.

{$DOMAIN} {
    tls internal
    @api path /rest/v1/* /api*
    route @api {
		rate_limit {
			zone my_zone {
				key {remote_host}
				window 1m
				events 20
			}
		}

		reverse_proxy node-app:8000
	}

	route {
		basic_auth {
			{$CADDY_AUTH_USERNAME} {$CADDY_AUTH_PASSWORD}
		}

		reverse_proxy dashboard:3000
	}

	handle_errors 429 {
		respond "You're being rate limited"
	}
}

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