LinuxnetworkingTested on real hardware

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
Shellbash
Updated
Script
bash
#!/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.

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 -4 on the server; it starts with 100.).
  • Your Plex account token — see Finding an authentication token.
  • curl on 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.z with your server’s Tailscale IP, 192.168.1.0/24 with your home subnet, and YOUR_PLEX_TOKEN with your Plex token. Leave 100.64.0.0/10 exactly 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. LanNetworksBandwidth overrides Plex’s automatic local-network detection. If you set it to 100.64.0.0/10 alone, 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/sessions reports location="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 PUT form sends the parameters as a URL-encoded query string, which is how the Plex /:/prefs endpoint expects them — --data-urlencode handles the commas and slashes safely.