Proxy + Without directive does not work

My Caddy version (caddy -version):

Caddy v.1.0.3

The problem I’m having:

I’m trying to proxy: internally to which listens on “/” and does not allow to set a base url. I need to be able access it directly via too, not just via

What I already tried:

I have tried both and iterations of it: {
  proxy /app {
    without /app
} {
  proxy / {
    without /app

If I manually enter it loads without css (it tries to load from “/”) otherwise the application redirects from to

Is there some sort of directive where you can route from the application to outside? I assumed “without” would do that internally too, so say if the application requests from inside to outside “/file.css” that would turn into whatever the “without” directive removed, e.g. “/app/file.css”


Here’s the problem: the program at thinks it’s running in the web root. I’ve written on this topic a bit before:

The “other methods” I mention at the bottom there are HTML filtering with the filter plugin as well as an undocumented feature of proxy that allows regex rewriting of returning headers. You’ll need to capture all instances of links to subresources that aren’t already prepended with your chosen subfolder and then prefix them with that correct subfolder.
Regex rewriting of upstream/downstream headers in proxy by comp500 · Pull Request #2144 · caddyserver/caddy · GitHub

First of all thanks! looking at both of the resources, one seemingly is for v2, which sadly isn’t stable enough yet, http.filter on the other hand looks interesting, though I am not sure how I would be able to use it to redirect only the internal calls to the subfolder, to avoid infinite redirects and such, basically whatever the internal app requests at / route it to the subfolder, e.g. /app

None of the resources I just linked reference v2, it’s all relevant to v1 as I noted your v1 Caddyfile configuration.

Filter doesn’t redirect, it changes HTML being returned on the fly. You would instruct it to look for script, link, anchor tags etc and do regex replacements on the places they link to. It requires a working knowledge of regex as well as the exact format the app outputs its links.

The undocumented proxy feature for header replacement would be used for Location headers whenever the app issues redirects and requires a similar knowledge of exactly how the app formats the content of those headers.

Now the question would be, is location absolute or relative paths, e.g. /styles.css or e.g., if it’s the latter it should be somewhat “easy” to just replace with, does that sound doable with the proxy feature?

It’s regex replacement, so with the right expression, you could feasibly handle any format.

You’ll need to investigate the app’s responses and craft the regex to suit, in both cases.

Is there any way I could “debug” the paths it requests? since I have no idea what paths the proxy module sees, I could only inspect in the network tab of dev-tools and the likes.

The proxy module is effectively a web client. It simply makes a HTTP request to the upstream much like a browser would, and it doesn’t get any special treatment. It sees the same thing you would.

You can use a tool like curl or browse to the upstream server in your browser manually with the developer tools open to inspect the exact responses.

Looking at what the upstream (downstream?) requests, it’s requesting full paths, so it should be just replacing the domain+root with domain+subfolder, I’ll experiment with it and try my luck, if nothing works I’ll post here what I tried and maybe you or somebody can further help (new thread or this one?). Appreciate all your input btw, thanks!

1 Like

No worries. This thread is as good as any to continue in if you like.

As a general strategy I’d recommend browsing to the site with developer tools open on the Network tab and then note every sub-request that fails. For each failed sub-request, then go and browse the page HTML for the tags that initiate that request, note how it is formatted, and then write a regex for it. Try to keep the regex as generic as possible and you’ll be able to filter multiple instances of the same tag in one rule. Reload the page, rinse and repeat until there are no failed sub-requests.

For the redirects it can be a bit tricky if the browser immediately follows the redirect and the Network tab loads the new page immediately. Using curl with the -I flag by default won’t follow the redirect and will show the response headers, including Location, so that might be the easiest way to figure out the formatting of that one.

1 Like

Thanks, I will experiment plenty tomorrow, curl will come in handy I’m sure! :smile:

1 Like

Looking at the docs redir looked even better, though neither redir or filter seem to work at all, even with just some basic tests:

just a simple redir: redir /login /app/login 307

a full match redir:

  redir 307 {
    if {>X-Forwarded-Proto} is http
    /  http://{host}/app/{uri}

A regex matching filter:

  filter rule {
      path .*10\.2\.0\.4\/.*
      search_pattern 10\.2\.0\.4\/
      replacement ""

and one more:

  filter rule {
    search_pattern http:\/\/10\.2\.0\.4\/
    replacement ""

In curl I can see the request going to 302 found via Location:

Hey @caddyblueyellow, I’m terribly sorry to do this - it’s something I pretty much never do - but I’m straight up going to have to tap out of this one at this point.

While I wish you all the luck in getting it working - and I know it can, I’ve spent the hours of effort fiddling about learning how to do it for one of my apps I just really wanted to work in a subfolder before and had success.

But I don’t know your upstream apps, I can’t see the exact data coming and going or how it needs to be manipulated. And even if I was there in person with hands on the data, last time I did it it took me literal hours to get a working end result. It was messy and complicated but it functioned… Until the app eventually changed the way it issued links in one update. I did explicitly say in the thread I linked earlier:

So again I’m sorry to just straight up tap out, but rather than spend probably days going back and forth and trying to pick it apart through the lens of your forum posts, I’m going to simply say that my strong recommendation is to give it a subdomain and be done with it.


No worries, I came from nginx where it was an absolute pain too, I just was naive to think without would internally take care of it or there was some sort of “magic” directive that easily fixes this issue in caddy, it’s pretty much the same nightmare in nginx.

I’ll just make a domain resolve to local IPs I guess and that should solve it :smiley: thanks for all still though!

1 Like

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