Plex over Tailscale: Direct-Connection Prefs
Point a headless Plex server at its Tailscale IP so remote apps connect directly at full speed instead of the 2 Mbps relay — set over the Plex API, no port forwarding.
DistrosAny Plex Media Server host
Shell
bashUpdated
Script
#!/usr/bin/env bash
# Point Plex at your Tailscale IP for direct, full-speed remote streaming.
# No port forwarding. Run from any device that is on your tailnet.
# --- Replace these three values first ---
PLEX_TS_IP="100.x.y.z" # your Plex server's Tailscale IP (starts with 100.)
HOME_SUBNET="192.168.1.0/24" # your real home subnet
PLEX_TOKEN="YOUR_PLEX_TOKEN" # your Plex account token
# ----------------------------------------
BASE="http://${PLEX_TS_IP}:32400"
# 1) Advertise the Tailscale address so Plex apps try it before Relay.
curl -sf -G -X PUT "${BASE}/:/prefs" \
--data-urlencode "customConnections=http://${PLEX_TS_IP}:32400" \
--data-urlencode "X-Plex-Token=${PLEX_TOKEN}" && echo "customConnections set"
# 2) Treat BOTH your home subnet and the whole Tailscale range as LAN.
# Listing only the tailnet range would throttle your real home devices.
curl -sf -G -X PUT "${BASE}/:/prefs" \
--data-urlencode "LanNetworksBandwidth=${HOME_SUBNET},100.64.0.0/10" \
--data-urlencode "X-Plex-Token=${PLEX_TOKEN}" && echo "LanNetworksBandwidth set"
# 3) Restart Plex so it re-publishes its connection list, then confirm a
# tailnet client is classified as local. A local stream shows location="lan".
# (Restart command varies by platform, e.g. systemctl restart plexmediaserver.)
curl -sf "${BASE}/status/sessions?X-Plex-Token=${PLEX_TOKEN}" | grep -o 'location="[a-z]*"'
What this does
This sets the two Plex Media Server network preferences that turn a Tailscale connection into a direct one, so remote apps stream at full quality instead of falling back to Plex’s 2 Mbps Relay. It’s the headless, scriptable version of the walkthrough in Plex Remote Access Over Tailscale.
customConnectionspublishes your server’s Tailscale URL so apps have a direct address to try — Plex documents this field for VPN setups.LanNetworksBandwidthtells Plex which ranges count as local. Adding the100.64.0.0/10Tailscale range makes every tailnet client count as LAN — no relay, no remote cap.
What this stack is for
Everything in this guide automates managing and streaming media you have the rights to — your own rips, DRM-free purchases, home video, Linux ISOs, and public-domain or Creative Commons releases. Downloading copyrighted material you haven't paid for is illegal in most places, and it isn't what this guide teaches. What you point these tools at is on you.
Prerequisites
- Tailscale installed and signed in on both the Plex server and the client device, on the same tailnet.
- The Plex server’s Tailscale IP (run
tailscale ip -4on the server; it starts with100.). - Your Plex account token — see Finding an authentication token.
curlon the machine you run this from (any device on the tailnet can reach the server).
Notes
- Make these values your own before running. Replace
100.x.y.zwith your server’s Tailscale IP,192.168.1.0/24with your home subnet, andYOUR_PLEX_TOKENwith your Plex token. Leave100.64.0.0/10exactly as-is — it is the fixed range every Tailscale device draws its IP from, not something specific to your machine. If a value looks specific to one machine, it’s a placeholder to change — not a literal to copy. Keep your Plex token in your secret store, never pasted into a saved note. - Never list only the tailnet range.
LanNetworksBandwidthoverrides Plex’s automatic local-network detection. If you set it to100.64.0.0/10alone, every device on your real home LAN is reclassified as remote, hits the remote bitrate cap, and 4K stops playing at home. The value must always contain both your home subnet and the tailnet range. - The Remote Access banner stays cosmetic. Your server’s Settings → Remote Access page may still show “Relay” because it tracks the public port-forward path you’re intentionally not using. As long as
status/sessionsreportslocation="lan"for a tailnet client, the direct path is working. - This opens no inbound port. Tailscale reaches the server through NAT without port forwarding over an encrypted WireGuard tunnel, so nothing on your router is exposed to the internet.
- The
curl -G -X PUTform sends the parameters as a URL-encoded query string, which is how the Plex/:/prefsendpoint expects them —--data-urlencodehandles the commas and slashes safely.