this post was submitted on 18 Aug 2023
18 points (90.9% liked)

Selfhosted

40198 readers
961 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 1 year ago
MODERATORS
 

So I have a webserver running nginx, and I want to use it as a reverse proxy to access web applications running elsewhere. I know this is a pretty standard use case, and that the traditional approach is to use virtual hosts to proxy the different apps.

Like, normally you would do something like:

I am familiar with this approach, and know how to set it up.

In this case, there is a catch though. For reasons that I can't get into here, I can't use virtual hosts, and everything should be hosted in the same webserver.something domain. So I thought I would use a subpath to host each app.

What I want to do is this basically:

In my nginx config file I have something like this:

upstream app1 {
  server app1.host:3000;
}

server {
    ...
    location /app1 {
        proxy_pass http://app1/;
    }
    ...
}

This works to the extent that all requests going to /app1/* get forwarded to the correct application host. The issue though is that the application itself uses absolute paths to reference some resources. For example, app1 will try to reference a resource like /_app/something/something.js, which of course produces a 404 error.

I suppose that for this particular error I could map /_app/ to the app1 application host with another location statement, but that seems dirty to me and I don't like it. First off it could quickly become a game of whack-a-mole, trying to get all the absolute paths remapped, and secondly it could easily lead to conflicts if other applications use that absolute path too.

So I guess my question is: is there a way to do this cleanly, and dynamically rewrite those absolute paths per app?

top 12 comments
sorted by: hot top controversial new old
[–] SeriousBug@infosec.pub 7 points 1 year ago (1 children)

You'll need to check the documentation of every app, they usually have an option to set a base path so the app will add that base path to every link and resource.

If some of the apps don't have support for that, the next option would be to build from source and patch all the links yourself.

[–] SpaceCadet@sopuli.xyz 3 points 1 year ago

I was afraid it was going to come down to that. I have been looking into configuration options for the apps, but they're 3rd party nodejs apps and I know jack shit about nodejs so I've had no luck with it so far.

Going with vhosts anyway (despite the pains it will create on this setup) seems to be the preferred way forward then.

Thanks for the insight, and for confirming what I already suspected.

[–] easydnesto@sh.itjust.works 2 points 1 year ago

I tried something like this with Traefik just recently using add prefix and strip prefix rules. It had limited success until until I encountered an application that doesn’t have everything behind a sub path, Like /lovelace (home assistant)or something like that. If the application just basis it off the host with a root path, than you can’t really apply the prefix rule as the reverse proxy will not know how to route the request as the application is asking for a path that is not already a sub. You may come into this situation more often with several applications. I ended up just switching back to virtual hosts myself.

[–] CameronDev@programming.dev 1 points 1 year ago* (last edited 1 year ago) (1 children)

This is part of my config that does something similar, hopefully it helps?:

location /dynmap {
        rewrite ^/dynmap/(.*) /$1 break;
        proxy_pass http://192.168.1.100:8123/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host$uri;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-NginX-Proxy true;
        proxy_cache_key "$host$uri";
        proxy_cache_valid 200 302 60m;
        proxy_cache_valid 404     10m;
        proxy_cache_use_stale error timeout invalid_header updating http_500 http_503 http_504;
        proxy_connect_timeout 10;
        index  index.html index.htm;
    }
    location /bluemap {
        rewrite ^/bluemap/(.*) /$1 break;
        proxy_pass http://192.168.1.100:8100/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host$uri;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-NginX-Proxy true;
        proxy_cache_key "$host$uri";
        proxy_cache_valid 200 302 60m;
        proxy_cache_valid 404     10m;
        proxy_cache_use_stale error timeout invalid_header updating http_500 http_503 http_504;
        proxy_connect_timeout 10;
        index  index.html index.htm;
    }

I suspect you need the rewrites?

[–] SpaceCadet@sopuli.xyz 2 points 1 year ago* (last edited 1 year ago) (1 children)

Hmm no, that's not really it... that's more so that you don't pass URLs starting with /app1/ onwards to the application, which would not be aware of that subpath.

I think I need something that intercepts the content being served to the client, and inserts /app1/ into all hardcoded absolute paths.

For example, let's say on app1's root I have an index.html that contains:

...
src="/static/image.jpg"
...

It should be dynamically served as:

...
src="/app1/static/image.jpg"
...
[–] CameronDev@programming.dev 4 points 1 year ago (1 children)

Ah, I see your problem, that is definitely trickier. Sorry for the lack of help :/

The wackamole method you described is something I have seen, no idea if it's the best approach though. Dynamic rewriting may be non-trivial as well.

A possibly suitable/worse approach could be to write a quick html page with IFrames and embed each app in an full screen IFrame :) I have that in my nginx as well :/

[–] SpaceCadet@sopuli.xyz 4 points 1 year ago (1 children)

No worries, your input was helpful and informative anyway, so thanks.

Going with vhosts anyway seems to be the least cumbersome route at this point.

[–] Cpo@lemm.ee 4 points 1 year ago

May I comments you both for the openness, politeness and helpfulness displayed here?

Thanks!

I also found the response informative, and thanks for making lemmy/fediverse happen!

[–] Decronym@lemmy.decronym.xyz 1 points 1 year ago* (last edited 1 year ago)

Acronyms, initialisms, abbreviations, contractions, and other phrases which expand to something larger, that I've seen in this thread:

Fewer Letters More Letters
DNS Domain Name Service/System
HTTP Hypertext Transfer Protocol, the Web
IP Internet Protocol
SSL Secure Sockets Layer, for transparent encryption
TLS Transport Layer Security, supersedes SSL
nginx Popular HTTP server

5 acronyms in this thread; the most compressed thread commented on today has 5 acronyms.

[Thread #61 for this sub, first seen 18th Aug 2023, 14:05] [FAQ] [Full list] [Contact] [Source code]

[–] Aux@lemmy.world 0 points 1 year ago (1 children)

Apps control the URLs. They either provide configuration for that and then you have to set them up manually, or they don't and you're screwed. Use sub-domains. You can use the wildcard domain (*) to point everything to the same IP address and then let nginx deal with it.

[–] SpaceCadet@sopuli.xyz 1 points 1 year ago* (last edited 1 year ago) (1 children)

You can use the wildcard domain

Yeah the problem was more that this machine is running on a network where I don't really control the DNS. That is to say, there's a shitty ISP router with DHCP and automatic dynamic DNS baked in, but no way to add additional manual entries for vhosts.

I thought about screwing with the /etc/hosts file to get around it but what I ended up doing instead is installing a pihole docker for DNS (something I had been contemplating anyway), pointing it to the router's DNS, so every local DNS name still resolves, and then added manual entries for the vhosts.

Another issue I didn't really want to deal with was regenerating the TLS certificate for the nginx server to make it valid for every vhost, but I just bit through that bullet.

[–] Aux@lemmy.world 0 points 1 year ago

If you're serious about self hosting, you shouldn't use an ISP router. Buy a proper router which will allow you to dynamically manage DNS records. My recommendation would be top end ASUS routers.

For SSL certificate management, use https://nginxproxymanager.com/ You just add a new domain there and it will fetch and manage a certificate for the domain.