Multiple subdomains, same app server, different routes

1. Caddy version (caddy version):


2. How I run Caddy:

Caddy is run from the standard docker image as part of a larger docker-compose config. A volume is used to make the Caddyfile accessible. Another volume is used to cache all letsencrypt info.

Spring Boot runs in another container, and it serves several resources of different purposes and for different audiences with different roles.

a. System environment:

Digital Ocean droplet running Ubuntu 20.04

b. Command:


c. Service/unit/compose file:


d. My complete Caddyfile or JSON config:


3. The problem I’m having:

I’m not sure how to do this. There are three types of routes in the same Spring Boot application. Some belong to Others belong to

There is no overlap between routes. /resource1 and /resource2 are only available at /resource 8 and /resource9 are only available at

This seems straightforward, but I’m not sure what the right way to do this is. Should I use handle or handle_path or a reverse_proxy with a named matcher? I just need some guidance, please.

4. Error messages and/or full log output:


5. What I already tried: {
reverse_proxy /resourceA
This serves the page, but I found that my .css file returns 0 content-length, so there is no styling. It’s not a 404. It just has no content.

6. Links to relevant resources:


Path matching in Caddy v2 is exact. That means that a matcher like /resourceA will only match /resourceA and not /resourceA/foo. You need to add a * to the end of the path matcher to make it match everything under it.

When Caddy passes a request through the configured handlers, but nothing handles it, then it returns an empty successful response. Because really, Caddy did exactly what you told it to do.

It depends.

The handle_path directive will strip the specified path prefix before executing the handlers within, so that can be useful if you need to “hide” the fact that you’re running under a certain path, but handle_path only supports one path at a time.

You can use a named matcher with handle if you need to match against multiple paths and handle them the same way.

1 Like {
        reverse_proxy /docs/*
        reverse_proxy /authorization-code/callback*
        reverse_proxy /oauth2/*

We are confused about when to use reverse_proxy vs handle/handle_path. Is the above config okay, or would handle be better?

You could do the same with a named matcher this way: {
	@allowed path /docs/* /authorization-code/callback* /oauth2/*
	reverse_proxy @allowed

Or you could use a handle:

	@allowed path /docs/* /authorization-code/callback* /oauth2/*
	handle @allowed {

	# Fallback for any requests not otherwise handled
	handle {


The later lets you control more easily what to do with requests that aren’t matched by your other handle blocks, because handle has the property of being mutually exclusive with other handle blocks.

Honestly, this is all really vague because we’re not talking about specifics of your app. It would be better if you were specific about what you want to happen, then I can help you craft something that is a closer fit for what you need.


I really, Really, REALLY appreciate how responsive and helpful you guys are at Caddy. Whenever we have a question, we know help is not far away, and we never have to wait long. It is greatly appreciated!


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