# Jellyfin on Olares ## Service Overview | Property | Value | |----------|-------| | **Host** | olares (192.168.0.145) | | **Platform** | Olares Marketplace (K3s) | | **Namespace** | `jellyfin-vishinator` | | **Image** | `docker.io/beclab/jellyfin-jellyfin:10.11.6` | | **LAN Access** | `http://192.168.0.145:30096` | | **Olares Proxy** | `https://7e89d2a1.vishinator.olares.com` | | **GPU** | NVIDIA RTX 5090 Max-Q (24GB) — hardware transcoding | ## Purpose Jellyfin media server on Olares with NVIDIA GPU hardware transcoding and NFS media from Atlantis. Replaces a previous Plex attempt (Plex had issues with Olares proxy auth and indirect connections from desktop apps). ## Architecture ``` Atlantis NAS (192.168.0.200) └─ NFS: /volume1/data/media └─ mounted on olares at /mnt/atlantis_media (fstab) └─ hostPath volume in Jellyfin pod at /media (read-only) Olares K3s cluster └─ jellyfin-vishinator namespace └─ Deployment: jellyfin (2 containers) ├─ jellyfin (main app, port 8096) └─ olares-envoy-sidecar (Olares proxy) ``` ## Deployment Patches The Jellyfin app was installed from the Olares marketplace, then patched with `kubectl patch` for: ### 1. NFS Media Mount ```bash kubectl patch deployment jellyfin -n jellyfin-vishinator --type=json -p '[ {"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"atlantis-media","hostPath":{"path":"/mnt/atlantis_media","type":"Directory"}}}, {"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"atlantis-media","mountPath":"/media","readOnly":true}} ]' ``` ### 2. GPU Access (NVIDIA runtime + env vars) ```bash kubectl patch deployment jellyfin -n jellyfin-vishinator --type=json -p '[ {"op":"add","path":"/spec/template/spec/REDACTED_APP_PASSWORD","value":"nvidia"}, {"op":"add","path":"/spec/template/metadata/annotations","value":{"applications.app.bytetrade.io/gpu-inject":"true"}}, {"op":"replace","path":"/spec/template/spec/containers/0/resources/limits","value":{"cpu":"4","memory":"8Gi"}}, {"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"NVIDIA_VISIBLE_DEVICES","value":"all"}}, {"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"NVIDIA_DRIVER_CAPABILITIES","value":"all"}} ]' ``` **Important**: Do NOT request `nvidia.com/gpu` or `nvidia.com/gpumem` resources. HAMI's vGPU interceptor (`libvgpu.so` injected via `/etc/ld.so.preload`) causes ffmpeg to segfault (exit code 139) during CUDA transcode operations (especially `tonemap_cuda`). By omitting GPU resource requests, HAMI doesn't inject its interceptor, and Jellyfin gets direct GPU access via the nvidia runtime class. ### 3. HAMI Memory Override (if GPU resources are requested) If you do need HAMI GPU scheduling (e.g., to share GPU fairly with LLM workloads), override the memory limit: ```bash kubectl patch deployment jellyfin -n jellyfin-vishinator --type=json -p '[ {"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"CUDA_DEVICE_MEMORY_LIMIT_0","value":"8192m"}} ]' ``` Note: This alone does NOT fix the segfault — `libvgpu.so` in `/etc/ld.so.preload` is the root cause. ## LAN Access Olares's envoy proxy adds ~100ms per request, causing buffering on high-bitrate streams. Direct LAN access bypasses this. ### NodePort Service ```yaml apiVersion: v1 kind: Service metadata: name: jellyfin-lan namespace: jellyfin-vishinator spec: type: NodePort externalIPs: - 192.168.0.145 selector: app: jellyfin ports: - port: 8096 targetPort: 8096 nodePort: 30096 name: jellyfin-web ``` ### Calico GlobalNetworkPolicy Olares auto-creates restrictive NetworkPolicies (`app-np`) that block external LAN traffic and cannot be modified (admission webhook reverts changes). A Calico GlobalNetworkPolicy bypasses this: ```yaml apiVersion: crd.projectcalico.org/v1 kind: GlobalNetworkPolicy metadata: name: allow-lan-to-jellyfin spec: order: 100 selector: app == 'jellyfin' types: - Ingress ingress: - action: Allow source: nets: - 192.168.0.0/24 ``` This is the **correct** approach for LAN access on Olares. Alternatives that don't work: - Patching `app-np` NetworkPolicy — webhook reverts it - Adding custom NetworkPolicy — webhook deletes it - iptables rules on Calico chains — Calico reconciles and removes them ## Jellyfin Settings ### Hardware Transcoding In Dashboard > Playback > Transcoding: - **Hardware acceleration**: NVIDIA NVENC - **Hardware decoding**: All codecs enabled (H264, HEVC, VP9, AV1, etc.) - **Enhanced NVDEC**: Enabled - **Hardware encoding**: Enabled - **HEVC encoding**: Allowed - **AV1 encoding**: Allowed (RTX 5090 supports AV1 encode) - **Tone mapping**: Enabled (bt2390, HDR→SDR on GPU) ### Library Paths | Library | Path | |---------|------| | Movies | `/media/movies` | | TV Shows | `/media/tv` | | Anime | `/media/anime` | | Music | `/media/music` | | Audiobooks | `/media/audiobooks` | ## NFS Mount ``` # /etc/fstab on olares 192.168.0.200:/volume1/data/media /mnt/atlantis_media nfs rw,async,hard,intr,rsize=131072,wsize=131072 0 0 ``` ### Performance - Sequential read: 180-420 MB/s (varies by cache state) - More than sufficient for multiple 4K remux streams (~100 Mbps each) ## Known Issues - **Patches lost on Olares app update** — if Jellyfin is updated via the marketplace, the NFS mount and GPU patches need to be re-applied - **HAMI vGPU causes ffmpeg segfaults** — do NOT request `nvidia.com/gpu` resources; use nvidia runtime class without HAMI resource limits - **Olares proxy buffering** — use direct LAN access (`http://192.168.0.145:30096`) for streaming, not the Olares proxy URL - **GPU shared with Ollama** — both Jellyfin and Ollama access the full 24GB VRAM without HAMI partitioning; heavy concurrent use (4K transcode + large model inference) may cause OOM ## Maintenance ### Check status ```bash kubectl get pods -n jellyfin-vishinator kubectl exec -n jellyfin-vishinator deploy/jellyfin -c jellyfin -- nvidia-smi ``` ### Re-apply patches after update Run the kubectl patch commands from the Deployment Patches section above. ### Check transcoding ```bash # Is ffmpeg using GPU? kubectl exec -n jellyfin-vishinator deploy/jellyfin -c jellyfin -- nvidia-smi # Look for ffmpeg process with GPU memory usage # Check transcode logs kubectl logs -n jellyfin-vishinator deploy/jellyfin -c jellyfin | grep ffmpeg | tail -5 ``` --- **Last Updated**: 2026-04-03