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?
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.
It depends on if you want to access it from anywhere (or give others access), or if you’re only accessing your server from specific devices.
Since I only ever access my server from my phone or my desktop, I use Wireguard via wg-easy. You set it up as a docker container on your server and it gives you a neat web UI (defaults to port 51821) from which to add Wireguard clients. Once connected through Wireguard, you can access your services as if you’re on the server’s local network.
Note, you’ll of course have to open up a port for Wireguard on your router for this to work, the default being 51820.
wg-easy is fabulous! I use it too and I love it
Is it just you that needs access? VPN like Tailscale or Wireguard is the most secure option then, as it’s not exposing any services to the internet.
Otherwise a reverse proxy in front of things like Traefik or Nginx, make sure things are automatically updated ASAP, and make sure auth is enabled on the services.
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.
“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.
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 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.
Interested in this as well, posting a comment here just to find the post more easily:)
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.
It depends on your exact requirements and your definition of “secure”. Lots of people like software like Tailscale. And it’s relatively secure as it doesn’t expose the services to the public but instead is an VPN. I personally don’t like Cloudflare at all, but that’s also a popular solution to get services exposed to the public internet. What I do is just use NGinx or NginxProxyManager, open up a port in my firewall and be done with it. No extra tunnel providers required and no Cloudflare that could be able to snoop on my connections. It also opens up connections to everyone else, so your software needs to be properly protected with passwords. But yeah, I can see how you get a bazillion different recommendations. I’d say if you prioritize security and it’s just your devices connecting, and they can all install a special client, go for something like Tailscale.