I’ve been researching different ways to expose Docker containers to the internet. I have three services I want to expose: Jellyfin, Omnivore (Read-it-later app), and Overseerr.
I’ve come across lots of suggestions, like using Nginx with Cloudflared, but some people mention that streaming media goes against Cloudflared tunnel TOS, and instead recommend Tailscale, or Traefik, or setting up a WireGuard VPN, or using Nginx with a WireGuard VPN.
The amount of conflicting advice has left me confused. So, what would be the best approach to securely expose these containers?
Maybe something like this https://github.com/fosrl/pangolin
“Secure” and “exposed” are antonyms in this scenario, that’s the nature of the beast. I use Nginx which I have a domain pointing to. Worst case scenario, a hacker brute forces access to my container and mucks around within the confines. As I understand from a WireGuard VPN, there’s an added level of security. You have to use the VPN to get access to your home ports, and then you can access your Docker containers as configured. There’s an added layer of security.
Some things to consider:
- Do you have a target on your back?
- Does your container contain sensitive data?
- If so, does your container have access to external directories?
- Does your project have security options like Geo Blocking, rate limiting, etc?
I’ve been running some local servers for a few years only behind Nginx. So far nothing bad has happened. But that doesn’t mean something bad couldn’t happen later.
Thanks for the info.
Do you have a target on your back?
No.
Does your container contain sensitive data?
No.
If so, does your container have access to external directories?
I have a hard drive mounted to the media folder that Jellyfin can access, and also a config folder. Omnivore/Overseer will probably be similar once I add them. Could this be a problem?
- '/home/${USER}/server/configs/jellyfin:/config' - '/home/${USER}/server/media:/data/media'
Does your project have security options like Geo Blocking, rate limiting, etc?
That is a good idea. Thankyou
My preference is just Cloudflare with or without nginx. Not sure if you’re using a hypervisor or not but it makes things exceedingly easy and I feel plenty safe enough inside of a Cloudflare tunnel. I stream a lot of data from Jellyfin. All day long, several streams to several people for over a year now with no problems. Last I knew, Cloudflare removed the language about video streaming from their TOS. Not sure if that’s changed but functionality on my end hasn’t.
I am using Unraid but I’ve installed the Cloudflare tunnel in docker containers and TrueNAS without many issues. Takes a bit of copying/pasting to get set up but it’s not terrible and everything is very responsive to make sure you’re doing things correctly.
Networking is fun because there are literally infinite potential options. There really isn’t a best option. It’s just what do you prefer. In my case I like to write a docker compose and write a tailscale container into it. I then set the service I want to expose either to my own tailnet or to the internet through funnel or though this other implementation I came up with a while back that I still need to do a write up on. Either way here is a guide i wrote with some docs as reference on my forgejo (git alternative). Docs are kinda a mess but hopefully it makes sense enough to help you out.
I’ve noticed 🥲, which hopefully means there’s no horribly wrong choice. I am leaning towards Tailscale, or maybe WireGuard. Thanks for the docs
I just installed tailscape and it works for my needs. Will read up on your docs. Thx
Depending on your level of paranioia. First, you don’t expose your containers, but their port(s).
With a reverse proxy, you will likely expose only 1 port, 443, no matter how many apps/containers/ports it will be pointing internally. For this, having a proper dns setup will be key, and a service like cloudflare dns (not tunnel), which additionally you can proxy your proxy. Also, you will need certificates (letsencrypt) for your traffic to be encrypted. Here, everybody will potentially have access to your services.
Another option is a zero trust tunnel, but as you had seen streaming may break tos. It will be likely enforced if you stream a lot, but I seriously doubt you’ll get any problem by having sporadic one or two users.
Tailscale, you need to add all the devices you need to access your services into the mesh, and you’ll need to re-authenticate every one again every few months.
Setting up a VPN (selfhosted) will require your devices to sign into it when accessing your services, and it seems to me the best approach as this way you will nave the most control over your setting.
Don’t forget to mention that, for this to work, your ISP should provide you with public IP, because if on CGNAT you will have to go with something like tunnels or tailscale.
For Tailscale you can disable key expiry on select devices.
Twingate is another option if it’s just device to device networking and you trust all the devices that are in your network. It’s free for personal use and peer to peer so no issues with TOS if you’re streaming.
Lots of great ideas in this thread. It sounds like you prefer Jellyfin, but I always encourage people to consider Plex. Plex is excellent, and even if you prefer the features or interface of Jellyfin, you should never expose any application (Plex, Jellyfin, or otherwise) directly to the Internet. This should be non-negotiable. Plex uniquely solves for external access with the mobile/desktop apps and app.plex.tv by brokering client connections into your network without a NAT/PAT on your router or firewall. Plex also supports Google logins, which means that you can now have 2fa and potentially phishing-resistant 2fa if you secure your Google account with a passkey.
At my company we only expose our applications behind a WAF and firewall, and I see that some folks here have recommended Cloudflare. For those who may not know, it is no longer enough to simply rely on a firewall. When your application is built with components that may become vulnerable over time, it’s critical to use a WAF.