Homelab
Plex Performance
Fixing Plex 4K Playback: Client IP Preservation with externalTrafficPolicy
Overview
This article fixes Plex 4K playback buffering caused by Kubernetes SNAT. The default externalTrafficPolicy: Cluster routes traffic through any node and SNATs it to the pod, which adds an extra hop and processing overhead. We switch to externalTrafficPolicy: Local for direct routing to the node running Plex. This eliminates SNAT overhead and preserves client IPs so Plex correctly classifies them as LAN traffic.
| Tip: | Having trouble? See v1.10.3 for what your setup should look like after completing this article. |
Before You Begin
Prerequisites
- Plex Hardening completed
What We're Fixing
4K content has jitter/lag while 1080p content plays smoothly.
Diagnose the Issue
Check: Misclassified Client IP
While playing 4K content, check Plex dashboard (Settings → Status → Now Playing):
| Field | Value | Problem |
|---|---|---|
| Video | 4K (HEVC Rext) | OK |
| Mode | Direct Play | OK - no transcoding |
| Client IP | Remote (10.244.1.1) | Wrong - should be actual client IP |
| Bandwidth | LOCAL: 0 bps | Wrong - should show local traffic |
Plex sees the client as 10.244.1.1 (Kubernetes pod CIDR) instead of the actual client IP. Since 10.244.0.0/16 isn't in LAN Networks, Plex classifies it as "remote."
Check: Service Configuration
kubectl get svc -n plex -o jsonpath='{.items[0].spec.externalTrafficPolicy}' Result: Cluster (default)
With externalTrafficPolicy: Cluster, Kubernetes SNATs the source IP to the pod network. The original client IP is lost.
Root Cause
With externalTrafficPolicy: Cluster, traffic routes through any node then gets forwarded internally via SNAT. This extra network hop adds latency and processing overhead that disrupts smooth 4K streaming.
Configure Remote Streaming Settings
Before we fix client classification, configure Plex for remote streaming. These settings apply to actual remote clients (via frp later) so bandwidth won't be artificially limited.
Server Settings (One-Time UI)
Settings persist in plex-config-encrypted PVC.
Remote Access (Settings → Server → Remote Access)1:
| Setting | Value |
|---|---|
| Limit remote stream bitrate | Original (No limit) |
| Internet upload speed | Set based on speedtest |
Network (Settings → Server → Network):
| Setting | Value |
|---|---|
| LAN Networks | (see below) |
| Enable Relay | Unchecked |
| Treat WAN IP As LAN Bandwidth | Checked |
Set LAN Networks to include all trusted VLANs:
192.168.20.0/24,192.168.30.0/24,192.168.40.0/24 | VLAN | Subnet | Purpose |
|---|---|---|
| Things-Trusted | 192.168.20.0/24 | Smart TVs, Apple TV |
| Unrestricted-Trusted | 192.168.30.0/24 | Personal devices |
| Restricted-Trusted | 192.168.40.0/24 | Kids/restricted devices |
Client Settings (Per Device)
On each Plex client (Apple TV, etc.): Settings → Video Quality:
| Setting | Value |
|---|---|
| Auto Adjust Quality | Off |
| Home Streaming | Maximum |
| Internet Streaming | Maximum |
| Play smaller videos at original quality | On |
| Note: | True remote streaming (via frp) uses a different network path than local clients through SNAT. Remote performance will be tested when frp is configured. |
Fix Client Classification
We add externalTrafficPolicy: Local to the Plex service so it can see where requests actually come from.
HelmRelease: Add externalTrafficPolicy
k8s/apps/plex/helmrelease.yaml:
# ... existing config ...
values:
# ... existing values ...
service:
type: LoadBalancer
port: 32400
externalTrafficPolicy: Local # ADD: Preserve client source IPs | Policy | Behavior | Client IP Preserved? |
|---|---|---|
Cluster | SNAT to pod network, load-balance all nodes | No |
Local | Direct routing to node with pod | Yes |
| Note: | externalTrafficPolicy: Local requires the pod to run on a node that receives traffic. With a single-replica StatefulSet this should be fine. |
Git: Commit Traffic Policy
git add k8s/apps/plex/helmrelease.yaml
git commit -m "fix(plex): preserve client IPs with externalTrafficPolicy Local"
git push Flux: Sync Traffic Policy
flux reconcile source git flux-system
flux reconcile kustomization sync Verify Client Classification
Verify: Service Updated
kubectl get svc -n plex -o jsonpath='{.items[0].spec.externalTrafficPolicy}' Expected: Local
Verify: Correct Client IP
Play 4K content and verify in dashboard:
| Field | Before | After |
|---|---|---|
| Client IP | Remote (10.244.1.1) | Local (192.168.30.x) |
| Bandwidth | LOCAL: 0 bps | LOCAL: showing traffic |
Verify: 4K Playback
4K content should now play smoothly without buffering.
Resources
Footnotes
Plex, "Server Settings - Bandwidth and Transcoding Limits," support.plex.tv. Accessed: Mar. 1, 2026. [Online]. Available: https://support.plex.tv/articles/227715247-server-settings-bandwidth-and-transcoding-limits/ ↩