ToxicAven
(Jacob Herd)
November 6, 2021, 11:48pm
1
1. Caddy version (caddy version
):
v2.4.5
2. How I run Caddy:
I use the default Systemd caddy.service
unit.
a. System environment:
OS: Ubuntu 20.04.3 LTS x86_64
Kernel: 5.4.0-89-generic
SystemD
b. Command:
No extra commands to manage caddy are used other than restarting the systemd unit.
c. Service/unit/compose file:
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddyfile or JSON config:
i.toxicaven.dev {
reverse_proxy localhost:40115
}
toxicaven.dev {
reverse_proxy localhost:3000
}
haste.toxicaven.dev {
reverse_proxy localhost:7777
}
3. The problem I’m having:
I am attempting to have an express.js app (currently being served to i.toxicaven.dev via port 40115) run through toxicaven.dev/images without modifying what is being served to toxicaven.dev by a different express app.
4. Error messages and/or full log output:
No errors are provided, using any of the tried methods, aside from Internal Server Error
when attempting to access the toxicaven.dev/images endpoint.
5. What I already tried:
toxicaven.dev {
route /images* {
reverse_proxy localhost:40115
}
reverse_proxy localhost:3000
}
toxicaven.dev/images {
reverse_proxy localhost:40115
}
6. Links to relevant resources:
opened 12:51PM - 15 Apr 20 UTC
closed 09:27PM - 26 May 20 UTC
feature
discussion
#### Background
The [`reverse_proxy` directive](https://caddyserver.com/docs/… caddyfile/directives/reverse_proxy) does not strip the path of the request before forwarding the request upstream. For example, in the following configuration a request to `example.com/foo/bar` will result in an upstream request of `upstream:80/foo/bar` *(rather than `upstream:80/bar`)*.
```
example.com {
route /foo* {
reverse_proxy upstream:80
}
}
```
At least from my experience, I quite often want the path to not be included in the upstream request, as the upstream server is a microservice which is not aware that it is being reverse-proxied. A good example given in #2813 (where this issue originated) is using phpMyAdmin at the URL `/phpmyadmin`. The [`uri` directive](https://caddyserver.com/docs/caddyfile/directives/uri) can be used to achieve this and the configuration can be changed to something like this.
```
example.com {
route /foo* {
uri strip_prefix /foo
reverse_proxy upstream:80
}
}
```
#### Issue
As this seems to be a relatively common pattern, I imagine configurations like the following will become quite commonplace.
```
example.com {
route /api {
route /v1* {
uri strip_prefix /api/v1
reverse_proxy oldapi:80
}
route /v2* {
uri strip_prefix /api/v1
reverse_proxy newapi:80
}
}
route /docs* {
uri strip_prefix /docs
reverse_proxy docs:80
}
reverse_proxy website:80
}
```
Here there is a lot of duplication of paths, i.e. `/docs` is written twice. I would like to avoid this to make the configuration more succinct and because it could very easily lead to errors being accidentally introduced. For instance, if I change `/docs` to be `/documentation` I may forget to update `uri strip_prefix /docs` to `uri strip_prefix /documents`. In a more complex config like this one you can see how there may be more subtle errors with the api/ path as there is nesting too.
#### Ideas
I suggested a few ideas in #2813 and @francislavoie made some good points, also mentioning that in a lot of cases a subdomain may be preferred. Ideas that I have come up with are...
1. Change the default behaviour of `reverse_proxy` to strip out the path. Then you could simply add it back in by changing `reverse_proxy upstream:80` to `reverse_proxy upstream:80/foo`. However, @francislavoie pointed out that this could be a confusing change from the current behaviour in Caddy (both v1 and v2) and may be unintuitive to users who expect the path to be preserved.
2. Add an option to the `reverse_proxy` directive to strip the path something like in the following example. However, this seems to go against the good principle that the `reverse_proxy` directive should not be involved in URL rewrites.
```
route /foo* {
reverse_proxy upstream:80 {
strip_path
}
}
```
3. Introduce a new [placeholder](https://caddyserver.com/docs/conventions#placeholders) (for instance `{route}` perhaps) which would return the current path matched by Caddy. Then it could be used like so to remove the duplication. However, I'm not entirely sure that this expresses clearly what we are trying to achieve.
```
route /foo* {
uri strip_prefix {route}
reverse_proxy upstream:80
}
```
4. Similar to ideas 2 and 3, create a new option in the `uri` directive that allows the currently matched route to be stripped from the path like in the following. It could also take an optional argument of a maximum number of path segments to strip. However, this increases the complexity of the `uri` directive with more options.
```
route /foo* {
uri strip_route
reverse_proxy upstream:80
}
```
I'd be really interested to find out what use cases exist for this and whether there are any other ideas how to do this đź’ˇ
1 Like
In case you didn’t see it, please see this page in the docs:
That’s essentially the way to do it, but I’d adjust it to this:
toxicaven.dev {
handle /images* {
reverse_proxy localhost:40115
}
handle {
reverse_proxy localhost:3000
}
}
Turn on the debug global option in Caddy, the logs should show additional details, if it’s a problem with proxying.
Add this at the top of your Caddyfile:
{
debug
}
“Internal Server Error” probably means there was a problem with your express upstream app, though.
1 Like
ToxicAven
(Jacob Herd)
November 7, 2021, 4:11am
3
Thank you for the response! Unfortunately, this does not appear to work correctly, for some odd reason. using the caddyfile
i.toxicaven.dev {
reverse_proxy localhost:40115
}
toxicaven.dev {
handle /haste* {
reverse_proxy localhost:7777
}
handle {
reverse_proxy localhost:3000
}
}
haste.toxicaven.dev {
reverse_proxy localhost:7777
}
allows the Hastebin to load when using haste.toxicaven.dev
, but causes serious serving issues when using toxicaven.dev/haste
, although it does load the page. No abnormalities can be found with the normal toxicaven.dev
page. I will leave the caddyfile configuration enabled for now, as I am unsure of what could be causing this. No errors or anything worth noting in the journalctl
for caddy or the hastebin server.
When you use handle
, the request path will be preserved, i.e. /haste
will still be prefixed on the path sent upstream. Is that what you’re expecting to happen? Or are you expecting /haste
to be stripped off first?
If you need to strip the path prefix, you can use handle_path
instead of handle
.
Some additional reading, somewhat tangential:
Have you ever tried to reverse proxy an app into its own little subfolder of your domain name?
Makes things neat, doesn’t it? Using example.com/foo/ for one app, example.com/bar/ for another. If you’re coming here from one of the selfhosted communities, you might be thinking along the lines of example.com/sonarr/, example.com/radarr/ etc.
Chances are, you’ve tried some configuration along these lines:
example.com {
redir /sonarr /sonarr/
handle_path /sonarr/* {
reverse_proxy localhost…
1 Like
system
(system)
Closed
December 6, 2021, 11:49pm
5
This topic was automatically closed after 30 days. New replies are no longer allowed.