Files
homelab-optimized/docs/services/individual/jellyfin-olares.md
Gitea Mirror Bot fb00a325d1
Some checks failed
Documentation / Build Docusaurus (push) Failing after 5m14s
Documentation / Deploy to GitHub Pages (push) Has been skipped
Sanitized mirror from private repository - 2026-04-18 11:19:59 UTC
2026-04-18 11:19:59 +00:00

6.4 KiB

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

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)

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:

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

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:

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

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

# 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