I just recently switched to an ISP that uses CGNAT. I needed a way to access my Plex server remotely now that I didn't have a public IPv4 address. Thankfully for most of my other web hosted projects, I was able to use Cloudflare tunnels. But it's ambigous if Cloudflare is okay with you using Tunnels for Plex traffic.
Instead people suggested buying a VPS and hosting a VPN (like Wireguard) to route your traffic through. I couldn't find a complete guide to do this. I struggled for a couple days with trial and error until I finally found a configuration that worked. I wanted to document this for anyone else in the same situation (and future me).
- Plex server hosted locally in a Docker container
- We'll be creating another Docker container running gluetun for the VPN tunnel in this tutorial
- A virtual private server (VPS) running either Ubuntu 22.04 or higher, Debian 11 or higher, CentOS 9 or higher
- Wireguard doesn't use much RAM, so I bought this 1 GB RAM VPS from RackNerd for $10.98/year.
So you have a fresh Linux server, first thing's first, let's secure it. See the steps to do that over here.
ufw default allow forward
command from the Firewall section.
Nyr has a nice automated script that you can run to streamline this part: https://github.com/Nyr/wireguard-install/
Run wget https://git.io/wireguard -O wireguard-install.sh && sudo bash wireguard-install.sh
to get started
At the end of this script you'll be prompted to add your first client. I named it plex
, but you can name it whatever you want.
Shout out to mochman's guide for help with this part.
- Open the wireguard config file that was created (
sudo nano /etc/wireguard/wg0.conf
). - Above the
[Peer]
section paste the following
PostUp = iptables -t nat -A PREROUTING -p tcp -i eth0 '!' --dport 22 -j DNAT --to-destination 10.7.0.2; iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 1.2.3.4
PostUp = iptables -t nat -A PREROUTING -p udp -i eth0 '!' --dport 51820 -j DNAT --to-destination 10.7.0.2;
PostDown = iptables -t nat -D PREROUTING -p tcp -i eth0 '!' --dport 22 -j DNAT --to-destination 10.7.0.2; iptables -t nat -D POSTROUTING -o eth0 -j SNAT --to-source 1.2.3.4
PostDown = iptables -t nat -D PREROUTING -p udp -i eth0 '!' --dport 51820 -j DNAT --to-destination 10.7.0.2;
- Replace
1.2.3.4
with your VPS's IP. - If you've followed this guide from the beginning, you shouldn't need to change the
10.7.0.2
.- Otherwise change
10.7.0.2
to the IP address in/root/plex.conf
- Otherwise change
As mentioned in mochman's guide, this forwards all traffic (except SSH port 22 and Wireguard port 51820) over the Wireguard tunnel.
If you only want forward specific ports, follow the next section in mochman's guide instead. I chose to forward everything for simplicity's sake.
If you've made it this far, we've succesfully set up Wireguard on a VPS and added a new client.
Back on your local network, we're going to make a new Docker compose file. It will make your Plex container use Gluetun to tunnel to the VPS.
You'll need the contents of the client config file that was generated.
If you named yours plex
, like me, you can see the contents of it with sudo nano /root/plex.conf
[Interface]
Address = YOUR_ADDRESS
DNS = 1.1.1.1, 1.0.0.1
PrivateKey = YOUR_PRIVATE_KEY
[Peer]
PublicKey = YOUR_PUBLIC_KEY
PresharedKey = YOUR_PRESHARED_KEY
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = YOUR_VPS_IP:YOUR_WIREGUARD_PORT
PersistentKeepalive = 25
---
services:
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
# Only the 32400 port is required, the rest are optional. Read what the rest do here: https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/
- 32400:32400
# - 1900:1900/udp # These two ports were conflicting with something when I tried to deploy, so I've commented them out
# - 5353:5353/udp
- 8324:8324
- 32410:32410/udp
- 32412:32412/udp
- 32413:32413/udp
- 32414:32414/udp
- 32469:32469
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- WIREGUARD_ADDRESSES=YOUR_ADDRESS # Match plex.conf above
- WIREGUARD_PRIVATE_KEY=YOUR_PRIVATE_KEY # Match plex.conf above
- WIREGUARD_PUBLIC_KEY=YOUR_PUBLIC_KEY # Match plex.conf above
- WIREGUARD_PRESHARED_KEY=YOUR_PRESHARED_KEY # Match plex.conf above
- WIREGUARD_ENDPOINT_IP=YOUR_VPS_IP # Match plex.conf above
- WIREGUARD_ENDPOINT_PORT=YOUR_WIREGUARD_PORT # Match plex.conf above
- FIREWALL_VPN_INPUT_PORTS=32400 # Whatever port your Plex is using for external access
- FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24 # Change to your local subnet. Allows Plex to access devices on your local network (e.g. HDHomeRun)
volumes:
- /volume1/docker/gluetun:/gluetun # Change to your filesystem
restart: unless-stopped
plex: # You should use your existing Plex config below. The only required change is to change network_mode to "service:gluetun"
image: lscr.io/linuxserver/plex:latest
container_name: plex
# network_mode: host
network_mode: "service:gluetun"
devices:
- /dev/dri:/dev/dri
environment:
- PUID=1026
- PGID=101
- TZ=America/Los_Angeles
- VERSION=docker
volumes:
- /volume1/docker/plex:/config
- /volume1/Media:/media
- /volume1/Photos:/photos
restart: unless-stopped
Deploy your Docker compose file.
You may need to manually specify 32400
as your public port at Plex Server > Settings > Remote Access (click show advanced)
If all went well, you should be able to play your Plex media both locally and remotely! 🎉
You might notice with the current setup that even when you're watching Plex locally, it's playing as if you're remote (i.e. using your ISP bandwidth/data).
To fix this, change the following settings in Plex Server > Settings > Network (click show advanced):
- Set "LAN Networks" to something that covers both your local subnet and the gluetun docker subnet
- For example, I used
192.168.0.0/16
because this encompasses both my local network (192.168.1.0/24
) and the gluetun network (192.168.128.0/24
) - Another example: if your local network devices start with
192.168.1.x
and your gluetun docker network starts with172.18.0.x
, then you'd want to put192.168.1.0/24,172.18.0.0/24
in your Plex's "LAN Networks" setting.
- For example, I used
- Set "Custom server access URLs" to
http://192.168.1.3:32400,http://1.2.3.4:32400
- My local Plex is at
http://192.168.1.3:32400
, change this to yours - My VPS with Wireguard that Plex is tunneling through is at
http://1.2.3.4:32400
, change this to yours
- My local Plex is at
- Click "Save Changes" at the bottom of this page