OR'ing or AND'ing named matchers together

1. The problem I’m having:

I’m trying to combine three different matchers with an OR, so I don’t have to write

reverse_proxy @a foo:123
reverse_proxy @b foo:123
reverse_proxy @c foo:123

but can instead write

reverse_proxy @abc foo:123

I looked at the docs, but couldn’t find conclusive information.

2. Error messages and/or full log output:


3. Caddy version:


4. How I installed and ran Caddy:

a. System environment:

Official Docker image, Alpine variant.

b. Command:

docker compose up -d

(will use the default command from the official image, as I did not override it)

c. Service/unit/compose file:

version: "3"
        container_name: caddy
        image: caddy:2-alpine
        restart: unless-stopped
            - 80:80
            - 443:443
            - ./Caddyfile:/etc/caddy/Caddyfile:ro
            - ./data:/data
            - ./config:/config
            - caddy

d. My complete Caddy config:

Not really applicable, this is a simple isolated question.

5. Links to relevant resources:


Like the help template says, we’ll need your full unredacted config. It’s impossible for us to answer your question without it. That’s true generally, and especially in your case since each matcher is different.

As Matt said, we need specifics about what you’re trying to achieve. It absolutely is applicable.

The only way to do generalized AND/OR is by abusing the not matcher as per De Morgan’s laws (I gave a talk explaining this API Platform Conference 2022 - Francis Lavoie - What's New in Caddy, the webserver of API Platform - YouTube), or by using the expression matcher.

Please upgrade to the latest version, that’s quite an old version and is missing many of the new matcher features you probably need.

1 Like

Alright, my bad then.

Here’s the full config atm:

lemmy.tld {
    header {
        # Only connect to this site via HTTPS for the two years
        Strict-Transport-Security max-age=63072000

        # Various content security headers
        Referrer-Policy same-origin
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        # disable FLoC tracking
        Permissions-Policy interest-cohort=()

    @encode_mime {
        header Content-Type text/css 
        header Content-Type application/javascript 
        header Content-Type image/svg+xml
    encode @encode_mime gzip

    request_body {
        max_size 8MB

    @pictshare_regexp path_regexp pictshare_regexp \/pictshare\/(.*)
    redir @pictshare_regexp /pictrs/image/{re.pictshare_regexp.1} permanent

    @backendpath {
        path /api/*
        path /pictrs/*
        path /feeds/*
        path /nodeinfo/*
        path /.well-known/*
    @acceptheader {
        header Accept application/*
    @backendmethod method POST

    reverse_proxy @acceptheader  backend:1234
    reverse_proxy @backendmethod backend:1234
    reverse_proxy @backendpath   backend:1234 {
        transport http {
          versions 1.1

        header_up Upgrade {http.request.header.upgrade}
        header_up Connection upgrade

        header_down -Transfer-Encoding

        header_up X-Real-Ip {http.request.remote.host}

    reverse_proxy frontend:1234

Essentially, I’m trying to translate this nginx config to Caddy. It is working, but I was curious to know if there was a way to avoid writing those three lines.

You could write it like this:

@backend `
	path('/api/*', '/pictrs/*', '/feeds/*', '/nodeinfo/*', '/.well-known/*')
	|| header({'Accept': 'application/*'})
	|| method('POST')
reverse_proxy @backend backend:1234

This doesn’t really do anything for you. Caddy will negotiate the HTTP version with the upstream automatically. It enables HTTP 1.1 and HTTP 2 support, and turning off HTTP 2 support has no benefit really.

Remove these. Caddy passes through headers transparently, and supports websocket upgrades automatically.

You don’t need this either, Caddy’s proxy sets the X-Forwarded-For header which has the IP address of the remote connection.

Why do you remove this header? I doubt this is necessary.

It was a necessary fix for a downstream service, but I believe it has been fixed there and that directive is likely no longer needed.

mm, that’s certainly a way to do it yeah, but it’s rather messier. What would you do?
Would be really nice if Caddy had first party support for explicit AND’ing and OR’ing matchers.

I would do exactly this. It is the cleanest way.

See the talk I linked above, and you’ll see why it’s not that simple to implement otherwise.

Alright, if you say so :slight_smile:
I will have to watch that talk!

By the way, would you say I should worry about any of these?

Thank you a lot for your help :3

No. Caddy sets modern secure defaults for TLS.

Okay, thank you!

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