DEV Community

Tyler Smith
Tyler Smith

Posted on • Edited on • Originally published at caddyexamples.com

5

Routing multiple paths to a reverse proxy using Caddy

Sometimes your app will need to route a handful of paths to one service and all other paths to another. Caddy's named matchers allow you to define a set of path directives then route them all to a single reverse proxy.

:80 {
    bind 0.0.0.0
    encode zstd gzip
    @webapp {
        path /
        path /posts /posts/*
        path /tags /tags/*
        path /static /static/*
    }

    handle @webapp {
        reverse_proxy webapp:3000
    }
    handle {
        reverse_proxy wordpress:80
    }
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can omit the handle blocks:

:80 {
    bind 0.0.0.0
    encode zstd gzip
    @webapp {
        path /
        path /posts /posts/*
        path /tags /tags/*
        path /static /static/*
    }

    reverse_proxy @webapp webapp:3000
    reverse_proxy wordpress:80
}
Enter fullscreen mode Exit fullscreen mode

You may wonder why we're matching most path directives against two different routes, using path /posts /posts/* instead of path /posts*.

Using path /posts* could include paths that you don't intend to proxy. If we used path /posts* and path /static*, we would also match on the following routes:

  • /postscript
  • /posts-authors
  • /static-electricity
  • /static-site-generators

This may be the desired behavior in your application, but it's probably not.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (3)

Collapse
 
vaviloff profile image
Vaviloff

Thanks, that was very useful!

You could also shorten this config a little, for example to match both /path and /path/*, simply write /path*:

    @webapp {
        path /
        path /posts*
        path /tags*
        path /static*
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tylerlwsmith profile image
Tyler Smith

Hey Vaviloff, I'm glad you found the post useful!

You could shorten the config, but it may proxy requests to @webapp that you weren't expecting. With the configuration you posted, the following routes would also be proxied to @webapp:

  • /postscript
  • /posts-authors
  • /static-electricity
  • /static-site-generators

The config I posted will only match against /posts or /post/*, which I think is the behavior that most people are expecting.

I realize that this isn't obvious, so I added a section about it in my post above. Thank you for the feedback: it made this post better 🙂

Collapse
 
vaviloff profile image
Vaviloff

You could shorten the config, but it may proxy requests to @webapp that you weren't expecting

Ah, that's actually a very good point indeed, thanks for making a note!

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay