Routing multiple paths to a reverse proxy using Caddy
Tyler Smith

Tyler Smith @tylerlwsmith

About: I'm a software developer who writes about Laravel, JavaScript, Rails, Linux, Docker, WordPress and the tech industry. Follow me on Twitter @tylerlwsmith

Location:
Sacramento, California
Joined:
Apr 17, 2018

Routing multiple paths to a reverse proxy using Caddy

Publish Date: Jan 21 '24
5 3

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.

Comments 3 total

  • Vaviloff
    VaviloffDec 30, 2024

    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
    • Tyler Smith
      Tyler SmithDec 30, 2024

      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 🙂

      • Vaviloff
        VaviloffDec 31, 2024

        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!

Add comment