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.

  • cherrykraken
    link
    fedilink
    English
    arrow-up
    2
    Ā·
    15 days ago

    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.

    Iā€™m not surprised this worked, numbers are allowed in FQDNs, but an IP address is not entirely equivalent.

    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 would strongly suggest you to read up on the OSI model.

    Nginx only understands HTTP and HTTPS requests at Layer 7 (implicitly and strictly ports :80 and :443), and forwards or redirects them to Layer 4 destinations. (Nginx can technically handle other protocol requests via plugins, but that isnā€™t what you are looking for.)

    In NPM, the proxy host name should at least contain the Raspberry Piā€™s hostname, e.g. jellyfin.your-rpi-name. Or you could use the path location option, e.g. your-rpi-name with location /jellyfin. (I think the second option might work with network hostname auto-discovery, in which case pihole as a DNS may not be strictly necessary.)

    • Fedegenerate@lemmynsfw.comOP
      link
      fedilink
      English
      arrow-up
      1
      Ā·
      15 days ago

      Thank you for the reading material, itā€™ll be tonight project. I think Iā€™m just going to tell people if they want to join in the family immich/mealie/etc theyā€™ll just have to let me into their router. Theyā€™ll get memorable addresses out of it and adblocking too. Iā€™m pretty sure that setup is comfortably within my skill set. I thought long and hard about opening ports but the security needed is beyond me currently. Down side is cost and Iā€™ll be managing a bunch of boxe. But I can add updating them into the monthly maintenance and if/when they come back they can be repurposed into other projects.


      I tried /locations but my service would rewrite the URL and break itself. Iā€™d navigate to ā€œbox.ip/immichā€ and immich would change the address to ā€œbox.ip/loginā€ and hang.

      Iā€™d need to learn how to have npm lock ā€œbox.ip/immichā€ and let immich append ā€œ/loginā€. Iā€™ll leave my test VM up and just chip away at it. I think I need the ā€œrewriteā€ flag but Iā€™m getting dangerously close to just learning how to write an nginx config instead of having npm do it for me.

      Thanks again for the pointers