How to Expose DLNA (Jellyfin/Plex) in Kubernetes
If you are running a media server like Jellyfin, Plex, or Emby inside a Kubernetes cluster, you may notice that proprietary ISP Set-Top Boxes (like Orange TV, Roku, or locked-down Smart TVs) cannot find your server, even if they are on the same WiFi network.
These devices rely entirely on DLNA (Digital Living Network Alliance) / UPnP to discover media servers via UDP Multicast Broadcasts (specifically SSDP on UDP 239.255.255.250:1900).
The Problem: Overlay Network Isolation
Kubernetes runs pods inside an isolated overlay network (e.g., Flannel using 10.244.x.x). When your TV on 192.168.1.X sends a multicast broadcast, the physical router drops it at the bare-metal node's network interface. It is never routed into the virtual overlay network, so your media pod never hears it.
The Solution: hostNetwork
To solve this, we must attach the pod directly to the bare-metal node's physical network interface.
Step 1: Update the Deployment
Modify your Deployment manifest to add hostNetwork: true. Because the pod is now using the host's network, you must also set dnsPolicy: ClusterFirstWithHostNet so it can still resolve internal cluster services (like databases or other pods).
apiVersion: apps/v1
kind: Deployment
metadata:
name: jellyfin
spec:
template:
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
# ... containers ...
Apply the changes:
Step 2: Install the DLNA Plugin
Note: As of Jellyfin 10.9, DLNA was removed from the core application.
- Open the Jellyfin Web UI.
- Go to Dashboard -> Plugins -> Catalog.
- Install the DLNA plugin.
- Restart the Jellyfin pod (
kubectl rollout restart deployment jellyfin).
Step 3: Bind to the Physical Interface
When a pod runs in hostNetwork mode, it suddenly sees every virtual interface on the host machine (including docker0, flannel.1, cni0). By default, Jellyfin might mistakenly broadcast its DLNA signal out of the virtual cni0 interface (back into the cluster void!) instead of out of the physical Ethernet port.
- Open the Jellyfin Web UI.
- Go to Dashboard -> Networking.
- Scroll down to "Bind to local network address".
- Type in the exact physical IP address of the Kubernetes node it is running on (e.g.,
192.168.1.51). - Save the settings.
Your TV will now instantly discover the Jellyfin server via its native Media Center application!
Step 4: Fix "Format Not Supported" (Force Transcoding)
Even after discovering the server, your TV might throw a "Format Not Supported" error when trying to play a video (especially .mkv files or x265/HEVC video streams).
By default, the Default.xml DLNA profile falsely assumes all devices support these modern formats natively, causing Jellyfin to attempt a "Direct Stream" instead of transcoding.
To fix this, you must explicitly strip these unsupported formats from the configuration to force the hardware transcoder (NVIDIA GPU) to convert the video down to standard H.264:
- Ensure a Default User is selected in the Dashboard -> DLNA settings (so the anonymous TV connection inherits permissions to use the transcoder).
- Run an automated
sedscript against the persistent DLNA configuration file to rip outmkvandhevc:
# Strip mkv and hevc to force H.264 transcoding
kubectl exec -it -n media deploy/jellyfin -- sed -i 's/mkv,//g; s/,mkv//g; s/hevc,//g; s/,hevc//g; s/container="hevc"/container=""/g' /config/data/plugins/DLNA_11.0.0.0/profiles/Default.xml
# Ensure file ownership remains correct for the container
kubectl exec -it -n media deploy/jellyfin -- chown abc:abc /config/data/plugins/DLNA_11.0.0.0/profiles/Default.xml
# Restart the pod
kubectl rollout restart deployment jellyfin -n media