this post was submitted on 05 Nov 2024
22 points (92.3% liked)

Selfhosted

40313 readers
227 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
 

For legibility I split the post into: my current setup; the problem I'm trying to solve; the constraints for solving the problem; what I've tried and failed to do; and key questions.

When roasting me in the comments, go nuts, I'm not a complete beginner, but I wouldn't rank myself as an intermediate yet. My lab is almost entirely tteck scripts, and what isn't built by tteck are docker containers. My inexperience informs some of my decisions for example: I'm using nginxproxymanager because Nginx documentation is beyond me, I couldn't write a nginx.config and NPM makes reverse proxies accessible to me.

My Current setup

I have a Proxmox based home server running multiple services as LXCs (a servarr, jellyfin, immich, syncthing, paperless, etc. Locally my fiancée and I connect to our services. Using pihole-NginxProxyManager(NPM) @ "service.server" and that's good. Remotely we connect to key services over tailscale using tailscale's magic DNS @ "lxcname:port" and that works... fine. We each have a list of "service: address" and it's tolerable. Finally, my parents have a home server, that I manage, it is Debian based with much the same services running all in Docker (I need to move it to Podman, but I got shit to do). We run each others' off-site backup over tailscale-syncthing and that seems good. But, our media and photos are our own ecosystems.

The Problem

I would like to give someone (Bob) a box (a Pi, a minipc, a whatever). The sole function of this box is to act as a gateway for Bob's devices to connect to key LXCs on my tailnet. Thus Bob can enjoy my legally obtained media and back up their photos.

The constraints

These are in order of importance, I would be giving ground from the bottom up. The top two are non negotiable though.

A VPS has low to zero WAF. Otherwise I would have followed the well trodden ground.

Failsafe. If the box dies bob can't access jellyfin until I can be arsed to fix it. Otherwise, they experience no other inconvenience.

No requirement to install tailscale on Bob's devices. Some devices aren't compatible with tailscale: Amazon fire stick. A different bob does't want to install a VPN on their phone. Some devices I don't trust to be up to date and secure, I don't want them on my tailnet... I have no idea if the one degree of separation is any more secure, but it gives me the willies.

I'm pretty sure I can solve this using pihole-nginx-tailscale with my skillset. But then I have to get into bob's router, and maybe bob might not like that. If I could just give them a preconfigured box that would be ideal. They would have pretty addresses though.

I don't currently have a domain, I do plan to get one. I just don't currently have one.

My attempts and failures to solve the problem.

I've built a little VM to act as a box (box), it requests a static IP. On it I installed Mint (production would probably be DietPi or Debian) Tailscale,Docker (bare metal) and NPM as a container. In NPM I set a proxy host 192.168.box.IP to forward to 100.jellyfin.tailscale.IP:8096. I tested it by going to box.IP and jellyfin works. Next up Jellyseerr... I can't make another proxy host with the same domain name for obvious reasons.

I tried "box.IP:8096" as a domain name and NPM rejected it. I tried "box.IP/jellyfin" and NPM rejected that too (I'll try Locations in a bit). I tried both "service.box.IP" and "box.IP.service" and I'd obviously need to set up DNS for that. Look, I'm an idiot, I make no apologies. I know I can solve it by getting into their router, setting Pihole as their DNS, and going that route.

Next I tried Locations. The required hostname and port I set up as jellyfin.lxc.tailnet.IP:8096 and I set /jellyseerr to go to jellyseerr.lxc.tailnet.IP and immich set up the same way. Then I tested the services. Jellyfin works. Jellyseerr connects then immediately rewrites the URL from "box.IP/jellyseerr" to "box.IP/login" and then hangs. Immich does much the same thing. In desperation I asked chatGPT... the less said about that the better. Just know I've been at this a while.

Here's where I'm at: I have two Google terms left to learn about in an attempt to solve this. The first is "IP tables" the second is "tailscale subnet routers" and I have effort left to learn about one of them.

During this process I learned I could solve this problem thusly: give Bob a box. On this box is a number of virtual machines(vm). Each vm is dedicated to a single service, and what the fuck is that for a solution?! It would satisfy my all of my constraints though, its just ugly.

Key questions

Is my problem solvable by just giving someone a Pi with the setup pre-installed? If not I'll go the pihole-npm-tailnet and be happy. Bob'll connect to "service.box" and it'll proxy to "service.lxc.tailnet.IP".

Assuming I can give them a box. Is nginx the way forward? Should I be learning /Locations configs to stop jellyseerr's rewrite request. Forcing it to go to "box.IP/jellyseerr/login". Or, is there some other Google term I should be learning about.

Asssuming I can give them a box, and nginx alone is not useful to me. Is it subnet routers I should be learning about? They seem like a promising solution, but I'll need to learn how the addressing works... Or how any of it works... IP tables seem like another solution on the face of it. But both I don't know where to send bob without doing local DNS/CNAME shenanigans

Finally assuming I'm completely in the weeds and hopelessly lost... What is it I should I be learning about? A VPS I guess... There's a reason everyone is going that route., Documentation on this "box" concept isn't readily findable for a reason I imagine.

you are viewing a single comment's thread
view the rest of the comments
[–] maxwellfire@lemmy.world 2 points 2 weeks ago* (last edited 2 weeks ago) (1 children)

I don't know a lot about tailscale, but I think that's likely not relevant to what's possible (but maybe relevant to how to accomplish it).

It sounds like the main issue here is dns. If you wanted to/were okay with just IP based connections, then you could assign each service to a different port on Bob's box, and then have nginx point those ports at the relevant services. This should be very easy to do with a raw nginx config. I could write one for you if you wanted. It's pretty easy if you're not dealing with https/certificates (in which case this method won't work anyway).

Looking quickly on google for npm (which I've never used), this might require adding the ports to the docker config and then using that port in npn (Like here). This is likely the simplest solution.

If you want hostnames/https, then you need some sort of DNS. This is a bit harder. You can take over their router like you suggested. You could use public DNS that points at a private IP (this is the only way I'm suggesting to get public trusted ssl certificates).

You might be able to use mdns to get local DNS at Bob's house automatically, which would be very clean. You'd basically register like jellyseer.local and jellyfin.local on Bob's network from the box and then setup the proxy manager to proxy based on those domains. You might be able to just do avahi-publish -a -R jellyseer.local 192.168.box.ip and then avahi-publish -a -R jellyfin.local 192.168.box.ip. And then any client that supports mdns/avahi will be able to find the service at that host. You can then register those names nginx/npn and I think things should just work

To answer your questions directly

  1. Yes I think just a box can work
  2. I think locations are going to be a nightmare. don't use them if you can avoid it. Also plain nginx really isn't so bad, and you can learn pretty quickly. this is probably fine in npn though
  3. I don't think you need to dive into iptables or anything like that. Iptables would provide a lower level proxying (level 3 instead of like level 7), which could be useful if you're running non http services, but isn't necessary for 99% of web stuff.
  4. I think part of the problem might be working with higher level systems like npn, but a lot of it is just that networking involves so many layers and there are multiple solutions to any problem, all of which require knowing somewhat what's happening under the surface to understand why they're failing

I'd be happy to try and give more specifics if you choose a path similar to one of the above things.

[–] Fedegenerate@lemmynsfw.com 1 points 2 weeks ago

My initial inception of this box was to have it request a static IP so I knew "box.ip". Then tape then tape some thing like this:

Box.ip Service1:port Service2:port ....

Onto the case. Then in NPM have it proxy requests to "box.ip:8096" to "tailscale.ip:8096". But alas, I couldn't figure it out. I could get 1 service to work but not multiple.

I couldn't ask someone to write the config for me, but if you're certain it's doable then I'll learn to write a config. Thank you for the offer. I'm guessing for each service I tell nginx to "listen" at "port" instead of only listening to ports 80,443 and 81.

MDNS seems like an interesting solution though, I'm going to read about that now actually, thank you for highlighting that solution to me. If I could get that working that would be ideal. I'll have to check if the expected devices are compatible but that would make everyone's life easier if I could just setup a cronjob on startup.