Question on reverse proxying and general feedback on configuration


I have Caddy running and serving requests for a single domain. Each service, including caddy, runs in its own container. All the services have access to the same docker network.

What I want is to be able to map url paths to different services. Something like: → service1:5000/ → service1:5000/foo → service2:5001

The container names for my testing are caddy and iamfoo. Iamfoo is a simple golang service. It has a few endpoints: /api, /bench, etc…

My caddyfile looks like:

  admin :2019

(whoami) {
  reverse_proxy /whoami/* http://iamfoo:5000
  root * /data/public
  log {
    output stdout
} {
  tls certr key
  import whoami
} {
  import whoami

My questions are:

  1. What is the canonical way to implement reverse proxying for:
    /whoami → iamfoo:5000
    /whoami/bench → iamfoo:5000/bench
    /whoami/bar → iamfoo:5000/bar

Keep in mind that I also want to statically serve the root domain path /.

  1. I am going to have many more services coming. My strategy is going to be updating the Caddyfile and then do a -reload. Let me know if you have alternative suggestions for that.

Thank you.

I have tried something like:

(whoami) {
  reverse_proxy /whoami/ http://iamfoo:5000/
  reverse_proxy /whoami/bench http://iamfoo:5000/bench
  reverse_proxy /whoami/api http://iamfoo:5000/api
  root * /data/public
  log {
    output stdout

But it seems Caddy does not support that:

Error during parsing: for now, URLs for proxy upstreams only support scheme, host, and port components

I have also tried:

  8   handle /whoami/* {
  9     uri strip_prefix /whoami
 10     reverse_proxy / http://iamfoo:5000
 11   }

But I get a 404 when I hit curl -v -k

I think I found it:

6 (whoami) {
  7   handle /whoami/* {
  8     uri strip_prefix /whoami
  9     reverse_proxy /* http://iamfoo:5000
 10   }
 13   root * /data/public
 14   file_server
 15   log {
 16     output stdout
 17   }
 18 }

Let me know if that is idiomatic or there is a better way to do it.

Many apps won’t behave well at all when being proxied in a subpath. Much better in general to use subdomains for each one instead:

1 Like

Thank you, Francis.

I understand having dedicated subdomains is ideal but I don’t control the dns server. I have to go through a ticket system and the entries may take hours if not days to setup.

That is why I followed the path approach.

I am serving individual api endpoints so I should not have issues with this approach. If I need to serve html it will probably be single page apps and I can set the URLbase option.

Do you have any comments on better ways to dynamically create entries that map paths to other dockers services? Anyone has experience with this plugin?


CDP definitely works best with subdomains as well. You definitely can route by path as well with it, but it’s slightly more complicated to configure. It essentially just maps Docker labels to Caddyfile config, so you just need to figure out what Caddyfile you want for each service, then write the labels. CDP will merge sites with the same domain name.

What you need to decide is whether you need to strip the path prefix before proxying upstream, or not. If you do want to strip it, then handle_path is what you want to use. If not, then handle is what you want. {
	# With path stripping
	handle_path /whoami/* {
		reverse_proxy whoami:5000

	# No path stripping
	handle /something-else/* {
		reverse_proxy whatever:3000

	handle {
		# Fallback if none of the above handles matched
1 Like

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