Assuming the user will not be connecting over vpn, but is both remote and non-technical, how would you expose Jellyfin to them securely?

top 98 comments

sorted by: hot top controversial new old
[–] 90 points 5 months ago (1 child)

At the very minimum stick a reverse proxy in front like caddy, nginx, or Traefik. Then have some middleware like crowdsec to inspect what's going on. Then whitelist the IP or the country IP block.

There is much more but those would be the bare minimum.

  • source
  • hideshow 1 child comment
  • [–] 22 points 5 months ago* (last edited 5 months ago)

    I too would like to know more. Jellyfin has been something that I am still hesitating to expose online without a VPN.

    I have Plex behind a reverse proxy (HAproxy) with Crowdsec and firewall rules all behind Cloudflare. My firewall rules in HAproxy block access a few different ways, like if request are higher then 60 requests a second, or if there is strange path traversal. Used the following guide as a start.

    https://www.archy.net/building-a-native-fail2ban-with-haproxy-stick-tables/

  • source
  • parent
  • [–] 25 points 5 months ago (7 children)

    Possibly mTLS, which you'd configure in your reverse proxy. You could email them the certificate and instructions on installing it. I believe for Chromium browsers on Windows you basically just double click the cert and click through the wizard. Firefox I know has a thing in the settings for importing the cert. Android you just tap on the cert and make sure it opens with 'Certificate Installer' if it gives you the option.

  • source
  • hideshow 7 child comments
  • [–] 4 points 5 months ago (2 children)
  • [–] 7 points 5 months ago (1 child)

    Not a terrible idea but im not sure rokus or fire sticks or whatever even have this capability.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 1 point 5 months ago

    Yeah, good to do for web ui, but none of my friends and family ever use the web ui. They are all on TVs. VPNs are probably easier to setup than mTLS if you're having people use their computers.

  • source
  • parent
  • [–] 4 points 5 months ago (3 children)

    I recently did exactly this. Only works with the web UI, no apps support it, but working well and those without the cert just get a 400 error. Not sure if non technical tbh, since you will get warnings when adding your root certificates to any device, and that might scare some who don't understand what it does.

    Also set it up through wireguard, so can punch out of double NAT.

  • source
  • parent
  • hideshow 3 child comments
  • [–] 1 point 5 months ago (2 children)

    Only works with the web UI, no apps support it

    Yeah that's true.

    you will get warnings when adding your root certificates to any device

    It's not a root certificate, and I've never seen any warnings.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 months ago (1 child)

    You need the web site to use a certificate from the same root authority as your client certificate. Otherwise browsers won't present the certificate to the server. That means either warnings on connect or adding the root cert.

    I do think if you are doing it with them in person it is doable to add it.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 1 point 5 months ago

    You need the web site to use a certificate from the same root authority as your client certificate.

    I'm not sure if I've misunderstood you, but I use Lets Encrypt for the server's TLS, and then my own CA cert (which is only present on the webserver) for the client's mTLS and everything works fine, since it's the client that validates the server's cert and the server that validates the client's cert.

  • source
  • parent
  • [–] 13 points 5 months ago (7 children)

    The biggest problem with that Jellyfin to this day is that you can’t.

    Seems like every new open source selfhosted app implements OIDC compatibility, but for some reason, I can only assume is technical debt, Jellyfin hasn’t.

  • source
  • hideshow 7 child comments
  • [–] 2 points 5 months ago (3 children)

    Jellyfin had a third party plugin for OIDC. It was archived recently, but I heard Jellyfin has plans to implement it directly into the software. 🤞

  • source
  • parent
  • hideshow 3 child comments
  • [–] 1 point 5 months ago (2 children)

    The plugin was neat, but if the clients don’t support it, it’s pretty much useless.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 0 points 5 months ago (1 child)

    Mobile clients should use QuickConnect for it (statement by the sso plugin maintainer). Else it should work with everything that uses the WebUI.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 2 points 5 months ago*

    Quick connect is not SSO. Because the topic is about non-technical end user friendly solutions, this isn’t a great one because this requires your user to login using a web browser on a different device and then use that for the quick connect and it’s just more clunky than it should really be.

    It’s honestly easier in this situation to just configure your end users device with a mesh VPN like Tailscale or Netbird and then all they ever have to do is login with whatever password you gave them.

  • source
  • parent
  • [–] [S] 1 point 5 months ago (2 children)

    What exactly about jellyfin makes this oidc style access more difficult to manage?

  • source
  • parent
  • hideshow 2 child comments
  • [–] 13 points 5 months ago (4 children)

    For a remote and non-technical user I would say IP whitelisting offers a decent tradeoff.

    On your end you expose your jellyfin port to internet, but restrict at the router level to your user's client IP address as soon as you have it. Obviously in practice this works best if the address does not change often.

  • source
  • hideshow 4 child comments
  • [–] 4 points 5 months ago (1 child)

    Also not as ideal if their ISP uses CGNAT. Still waaay better than fully open, but you would be giving access to many households

  • source
  • parent
  • hideshow 1 child comment
  • [–] 2 points 5 months ago*

    Yep, that's why I call that a tradeoff. Far from perfect and yet so much better than nothing.

    Pros:

    • Likely cuts 99.99% of attacks.
    • Nothing to do on client's end.

    Cons:

    • Whitelisting must be updated everytime the client address changes.
    • Not 100% bulletproof as operators (notably for mobile networks) can NAT multiple connections behind a single publicly addressable IPv4 address.
    • Also IP addresses can be spoofed but I doubt that would be a major concern here.
  • source
  • parent
  • [–] 12 points 5 months ago

    To be totally honest I'm not sure you can harden jellyfin enough for public Internet exposure without also breaking basic functionality of the platform.

    This is why everyone is always pushing so hard for a VPN/Tailnet of some kind. The public internet is a bit to much of a wild west to be exposing arbitrary services to it unless you really know what you're doing.

  • source
  • [–] 11 points 5 months ago (8 children)

    Ask them to visit https://ipv4.icanhazip.com/ and give you back the number, then whitelist in your webserver, as well as your LAN/VPN range, deny rest. Explain they can only reach jellyfin from their home internet. Repeat if they get 403 forbidden after they get a new WAN IP.

    That or VPN like openziti, wireguard but gets more complicated.

  • source
  • hideshow 8 child comments
  • [–] 5 points 5 months ago (3 children)

    You really can't assume your visitors are going to have static IPs.

    What happens when they visit from their phone? A friend's WiFi? Their home connection that has a regularly changing IP?

  • source
  • parent
  • hideshow 3 child comments
  • [–] 1 point 5 months ago* (last edited 5 months ago) (2 children)

    So far I've seen WAN leases expire after a long time, say months, or quarter year, so is doable. If becomes an issue I'll work with them on a VPN solution but is a pain for non-technical users or non-supported hardware. That's also why I explain "use from your home network only".

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 months ago (1 child)

    What's your concern about running it behind a reverse proxy, like caddy or nginx?

  • source
  • parent
  • hideshow 1 child comment
  • [–] 11 points 5 months ago (1 child)

    if theyre close, add them to your tailscale, if not and you have a web serve, use a reverse proxy.

    for tailscale, you'd probably have to walk them through setting it up but then its one and done

  • source
  • hideshow 1 child comment
  • [–] 5 points 5 months ago

    That’s basically the VPN solution but with a little more flexibility.

    If you want to actually expose the service, you can use Tailscale to connect it to a VPS and then expose that port to the web with Nginx, but if you do that, be prepared on the security front because…you know…open internet be full of hazards.

  • source
  • parent
  • Depends on what you mean by "secure." My personal setup is Jellyfin LXC on proxmox --> Wireguard to VPS -> Nginx reverse proxy on VPS.

    This setup relies somewhat on Jellyfin's auth, but I'm comfortable with that risk. The LXC is blocked from sending local traffic on my network by firewall rules. Yes, someone could exploit a vulnerability in Jellyfin (though looking through the CVEs I'm not overly worried about that), then escape the LXC and fuck with my server. But that's a lot of work for no profit.

    For more protection (in sense of reducing traffic that even interacts with your server), I'd recommend getting a wildcard cert for the domain so that the actual subdomain jellyfin is on is undisclosed to anyone not using your service.

    Security isn't about making everything impregnable, it's about making attacks more trouble than they're worth. Otherwise, we'd all live in fortified bunkers surrounded by landmines. 🙃

  • source
  • hideshow 6 child comments
  • [–] 3 points 5 months ago (3 children)

    How much bandwidth is used via the VPS in this instance? I've seen most VPS in the USA have a limit of 1TB of bandwidth.

    How many users are you sharing with?

    I know Hetzner does 20TB bandwidth, but that is only EU servers as far as I know.

  • source
  • parent
  • hideshow 3 child comments
  • I have a very cheap ($11/yr) us-based vps through racknerd I got via low end box. I've got 12 users but only 5 really active ones and I've never come close to hitting the 1tb transfer. I serve several services through that one vps (all just reverse proxy to my homelab).

    I did just pick up another u.s. based vps through low end box the other day- $12/yr and unmetered Gbps. 1 CPU only, but a reverse proxy doesn't need a lot of compute. :)

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 months ago

    Thank you! I haven't heard of racknerd/low end box, I'll have to check them out. Yeah I'm not worried about the CPU just the bandwidth haha.

    I have 30 people on my Plex share and never had to care about bandwidth so I'm a bit worried for my end

  • source
  • parent
  • [–] 1 point 5 months ago* (last edited 5 months ago)

    And just looked them up, saw their $2 a month VPS has a 3TB bandwidth limit and I signed up immediately lol.

    Thank you!

    • and they have Los Angeles, which is perfect
  • source
  • parent
  • [–] 3 points 5 months ago (1 child)

    Your vps isn't doing anything useful security wise.. it's just sending traffic directly to jellyfin.

    You'd get the same protection with just port forwarding to a local proxy in front of jellyfin. Or you could even leave out the proxy if you didn't need it.

  • source
  • parent
  • hideshow 1 child comment
  • I'm aware of this (that's why I described a potential breach as Jellyfin -> LXC escape). What it does provide me is a static IP to point my domain at that I don't have to worry about updating via whatever DDNS service and that isn't tied to my home address. That and the wireguard tunnel gives me plausible deniability should my ISP ever decide to enforce its rules against hosting servers. 😀

  • source
  • parent
  • [–] 19 points 5 months ago (4 children)

    Run the jellyfin in a container that only has read privileges to the videos ( make sure you can't get out to your whole NAS from there), put that behind a Cloudflaired tunnel.

    It's not technically secure, but if they can't get a foothold in your network and the only thing they can access is your video catalog, that's a reasonable amount of risk.

  • source
  • hideshow 4 child comments
  • [–] 11 points 5 months ago (2 children)

    Gotta be careful with cloudflared and media. They can block you if they detect copyrighted materials, even if it's your own DVDs. You can setup TLS certs so the traffic is at least encrypted

  • source
  • parent
  • hideshow 2 child comments
  • [+] 4 points 5 months ago (1 child)
  • [–] 3 points 5 months ago

    Right. Which is why Cloudflared would block you if it's detected. But regardless, if for whatever reason, you ended up in court for the content you copied, the judge would probably give you a low fine. Obviously not legal advice, but the US justice system doesn't have time to care about people making digital copies of DVDs they've purchased.

    It's irrelevant anyway, since none of us are just copying our own DVDs... But for legal reasons /s

  • source
  • parent
  • [–] 9 points 5 months ago (2 children)

    call me crazy but I just use a couldflare tunnel since my domain is already provided through them. They make it really easy to add sub-domains attached to specific ports on the local machine and automatically adds the proper DNS entries. Additionally they have a ton of domain security/anti-bot measures you can set up.

  • source
  • hideshow 2 child comments
  • [–] 4 points 5 months ago (1 child)
  • [–] 9 points 5 months ago (1 child)

    I agree with the folks saying reverse proxy of some kind + WAF. That way end users don’t have to deal with the VPN, but your home system is not directly exposed.

    I’ve been doing something similar with SSH local port forwarding and a $5/month VPS. Haven’t come anywhere close to my network quotas, and performance has not been an issue for home use with 2-5 concurrent users most of the time. I forward the local caddy ports to unprivileged ports/user on the VPS, then use the firewall on the VPS to forward that port to 443 and lock down the rest.

  • source
  • hideshow 1 child comment
  • [–] 17 points 5 months ago (9 children)

    Secure is relative, you should be aware that jellyfin itself has security issues https://github.com/jellyfin/jellyfin/issues/5415 most of which are harmless, but at least one is fairly serious and allows people to watch your media without authentication, and adding an extra layer of authentication on the proxy would likely cause issues with clients.

    That being said, if you're okay with those security issues what I would do is have a cheap VPS, connect both machines to tailscale, and have something like Caddy on the VPS to do the forwarding.

  • source
  • hideshow 9 child comments
  • [–] 31 points 5 months ago (8 children)

    Just leaving this here

    Now, let's address this clearly once and for all. What is possible is unauthenticated streaming. Each item in a Jellyfin library has a UUID generated which is based on a checksum of the file path. So, theoretically, if someone knows your exact media paths, they could calculate the item IDs, and then use that ItemID to initiate an unauthenticated stream of the media. As far as we know this has never actually been seen in the wild. This does not affect anything else - all other configuration/management endpoints are behind user authentication. Is this suboptimal? Yes. Is this a massive red-flag security risk that actively exposes your data to the Internet? No.

    https://github.com/jellyfin/jellyfin/issues/5415#issuecomment-2825240290

  • source
  • parent
  • hideshow 8 child comments
  • [–] 6 points 5 months ago (5 children)

    Except most people have almost the same structure because of media organizers like radarr/sonarr. At the very least they should hide that behind a setting to not require auth (since the header should be there for most clients) so only people running an old client would be affected. They could also add an extra salt to that hash or something similar.

    I agree, it's not critical, but it shouldn't be hand waved either. And like I said, security is relative, I would argue for most people this is fine, but I still think this should be taken more seriously.

  • source
  • parent
  • hideshow 5 child comments
  • [–] 4 points 5 months ago (4 children)

    Yeah not only would a lot of people have the same media name, because of docker mounts, probably a lot of people have the same path to the media inside of the docker container even if the external location is different. I bet you could make a rainbow table of sorts of the most popular movie/TV torrents combined with the most common place in the container for media to be mounted, then use shodan to get a list of hundreds of instances that you could scan for the common hashes.

    I'm just seeing the issue for the first time and noticed it was raised 5 years ago - surely that was enough time to at least put forward a changeover date and give clients time to update.

  • source
  • parent
  • hideshow 4 child comments
  • [–] 3 points 5 months ago (3 children)

    Jokes on them, my paths are a shitshow and I can't be bothered to organize them properly

  • source
  • parent
  • hideshow 3 child comments
  • [–] 2 points 5 months ago* (last edited 5 months ago) (2 children)

    Do you not do any renaming? That probably would make it even easier as you can just brute force with a database of filenames scraped from torrents. I already have a proof of concept that generates valid jellyfin IDs from any given file path, it only takes a few more steps before you can plug in a shodan scan of jellyfin instances and just shotgun a bunch of IDs generated from torrents.csv at them and find stuff you can stream without authentication.

    People not bothering to rename, using the default radarr naming scheme, or everyone using the same naming pattern from trash guides just makes it easier.

    Probably the only way to guarantee nobody can probe your media and stream it without authentication is to make sure to rename everything using a format that only you use or mount all your media under a path inside docker that contains a long randomly generated folder prefix.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 months ago (1 child)

    I was mostly making the comment in jest. I do rename, but my folder structures, as someone who downloads everything manually based on what I want to watch rather than doing the automated *arr stuff leaves it in directories only I consider sensible.

    I have Jellyfin behind a reverse proxy that lives in a DMZ and a WAF to go with it. I'm sure there's still room for watching an unauthenticated stream because I forgot to rename a folder somewhere, but it's not exactly an attack vector I care about. I'm more concerned about DDoS or impersonation attacks, which I also attempt to mitigate via an LDAP implementation behind the scenes.

    It's not perfect, but it's the best effort I can make at the moment.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 1 point 5 months ago

    Yeah that's fair and I think that's a good move, my point is just that people are acting like this is not feasible to exploit. I'm at the point in my exploit testing excursion where I have a script that can generate a stream of potential IDs based on real torrent names being parsed and reformatted using radarr's default naming pattern as well as the commonly used trash guides ones permuted with some common library paths used in the default docker compose examples, and it's turning up actual ID matches with my jellyfin instance. All I have left to do is make it create API requests to test the IDs against the unauthenticated API instead of checking an exported list and there's a proof of concept. 5 years is a long time for someone to figure that out.

  • source
  • parent
  • [–] 8 points 5 months ago

    You can do a reverse proxy + authelia (or other auth service). It's still more risky than a VPN IMO, buts wayyyy better than some of the other options in this thread

  • source
  • [–] 7 points 5 months ago (6 children)
  • [–] 16 points 5 months ago (2 children)

    VPNs are not trivial to use for normies.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 19 points 5 months ago (2 children)

    Yeah, let me just walk my normie friends and parents through setting up a VPN on their TV so they can stream their shows.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 1 point 5 months ago

    I stuck a rPi in their houses that runs pihole+nginx+tailscale. As far as they're concerned they go to https://jellyfin.example.domain and they're there.

    Better yet, they go to http://homarr.notlocal and they have nice little icons to click on, that take them to all the front-end services I run.

    They get pihole goodness for free. Their homepage is attached to their pihole if they want to pause/stop it.

    I'd like to set them up to be more declarative than I have, setup/updating is a pain. Nix is interesting but the learning curve is too steep for the effort I'm willing to put in. As per usual, being lazy will end up being more work for me in the long run.

  • source
  • parent
  • [–] 7 points 5 months ago

    best practice states security through obscurity is not to be relied upon, but compare ssh logs after one year on the default port vs a non-standard port and you'll immediately see why you want to use a non-standard https port for non-professional services. it cuts 99.9% of the noise/attempts.

  • source
  • [–] 6 points 5 months ago

    I agree with reverse proxy + middleware. I’d also suggest something like Jellyswarm as the front end. That way I can connect to other friends’ servers too.

  • source
  • [–] 6 points 5 months ago (8 children)

    Set up a reverse proxy with https always on. And get a good (physical) firewall, preferably something akin to opnsense, pfsense, openwrt. Exposing is always a risk, and if you do want it, you have to bear the responsibility for your own security. Keep things up to date, set up monitoring and a good logging system (Wazuh) comes to mind.

    Exposure means a security risk. How you deal with that security risk is your choice.

    Cloudflare and the likes forbid usage of their stuff for these things.

  • source
  • hideshow 8 child comments
  • [+] 3 points 5 months ago (4 children)
  • [–] 4 points 5 months ago (1 child)

    By setting up a reverse proxy you redirect the traffic through that specific proxy which means less open ports (basically just 80/443), less monitoring, the ability to easily put a WAF inbetween, etc.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 3 points 5 months ago*

    You've got a couple benefits. If you have a domain name, and aren't advertising it publicly, then you can use the reverse proxy to point that domain to a non-standard port that Jellyfin runs on.

    Security through obscurity is not good security, but it does prevent the majority of port scanning attacks. You can also use fail2ban on the reverse proxy side to try and mitigate some attacks.

  • source
  • parent
  • [–] 1 point 5 months ago* (last edited 5 months ago) (2 children)

    Cf used to have it against the rules, but it's fine now.

    edit: you can in fact do video, but they have added lines about ~piracy

  • source
  • parent
  • hideshow 2 child comments
  • load more comments (-1 replies)
    [–] 6 points 5 months ago (2 children)

    Perhaps (and I know I might be weird) running pangolin on something like hetzner? (Which I do)

  • source
  • hideshow 2 child comments
  • [–] 6 points 5 months ago

    If they could be using web UI (I'm not sure how a client would work with auth like that) then it kind of depends on how much hassle they can live with and how secure you want to be

    Simplest would be to use https://doc.traefik.io/traefik/reference/routing-configuration/http/middlewares/basicauth/
    You set up username and password and share those with the user. But it can be brute-forced

    Something more secure but also a bit more demanding would be some kind of email otp
    https://docs.goauthentik.io/add-secure-apps/flows-stages/stages/authenticator_email/
    Set up authentik to send time-limited link to their email that well let them through. But they would have to authenticate every time they access

  • source
  • [–] 10 points 5 months ago (2 children)

    Another way:

    Expose using caddy. Use basic auth for the web UI only. This exempts the Jellyfin app clients from basic auth that they don’t support but requires it before anyone even gets to the Jellyfin UI. This obfuscates the fact that your endpoint is even a Jellyfin end point.

  • source
  • hideshow 2 child comments
  • [–] 5 points 5 months ago (6 children)

    Not at all, there's legal risk if you're hosting your blurays. Cloudflare even explicitly forbids such use. VPN or nothing imo.

  • source
  • hideshow 6 child comments
  • [–] 6 points 5 months ago (4 children)

    Wow, Cloudflare is against piracy? Every single site I've ever seen in my life is registered with Cloudflare and uses their DNS with the exception of PTB I believe.

  • source
  • parent
  • hideshow 4 child comments
  • [–] 9 points 5 months ago (1 child)

    Not sure about that, I think it's more just that they don't want people streaming terabytes of traffic through their edge.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 5 points 5 months ago

    Reverse proxy with fail2ban or crowdsec. It's possible to set up things like Pangolin which ultimately use a VPN between external and internal access points but not at the client, though it takes more setup if you want to use apps over pangolin instead of just the browser.

  • source
  • [–] 8 points 5 months ago

    A reverse proxy is what you are looking for. I recommend Caddy.

    You’ll also need a domain, but they can be had for very cheap.

  • source
  • load more comments
    view more: next ›