Skip to content

Jellyfin

Jellyfin is a free, open-source media server available at jellyfin.hdhomelab.com. It is the primary streaming server, pinned to worker-0a for Intel GPU access.


Deployment

Jellyfin runs in Kubernetes (media namespace) as a single-replica Deployment. Media is served read-only from the shared emby-media NFS volume.

graph LR
    User -->|HTTPS| Gateway[Cilium Gateway]
    Gateway --> Jellyfin[Jellyfin :8096]
    Jellyfin -->|read-only| Media[(NAS /volume1/media)]
    Jellyfin -->|config| LocalPVC[local-path PVC]
    CronJob[Hourly CronJob] -->|rsync| LocalPVC
    CronJob -->|backup| NFS[(NAS backup PVC)]
Hold "Alt" / "Option" to enable pan & zoom
  • URL


    jellyfin.hdhomelab.com

  • Namespace


    media

  • Image


    jellyfin/jellyfin

  • Node


    Pinned to worker-0a (Intel GPU)

  • Storage


    local-path config + shared emby-media NFS volume

  • Config


    flux/apps/noah/media/jellyfin/


Storage & Backup

Config uses local-path (SQLite performance) with an hourly rsync CronJob to NFS — see SQLite on Local Path for the pattern details and migration procedure.

Volume PVC Storage class Purpose
/config jellyfin-config local-path Database and metadata
/media emby-media syno-nfs-retain Shared NAS media library (read-only)

Shared media volume

Jellyfin and Emby share the same emby-media PVC (/volume1/media on the NAS).

Force a manual backup
kubectl create job --from=cronjob/jellyfin-config-backup jellyfin-config-backup-manual -n media

Client IP Logging

Real client IPs are logged automatically — no app-level configuration needed. The fix is at the network layer: the router forwards directly to Traefik's macvlan IP, bypassing Docker's userland proxy. See Client IP Preservation.


Key Configuration

Setting Value
TZ America/New_York
runAsUser / runAsGroup 1034 / 100
CPU request / limit 1 / 4
Memory request / limit 3 GiB / 8 GiB

Hardware transcoding

worker-0a has an Intel GPU. Hardware transcoding is not yet enabled — when ready, add gpu.intel.com/i915: "1" resource request and configure Dashboard → Playback → Hardware acceleration → Intel QSV.


Multi-Language Libraries

The media library is split into two language segments, each exposed as a separate Jellyfin virtual folder. The split is implemented via symlinks on the NAS — each language folder is a symlink pointing to the corresponding subdirectory under /volume1/media, mounted into Jellyfin as an additional virtual library.

Folder Content
Chinese (cn) Chinese-language films, series, and shows
English (en) English-language films and series

Access is per-user — users only see the folders they have been granted. This is enforced automatically on every login by jellyfin-librarian based on the user's jellyfin_libraries attribute in Authentik.

jellyfin_libraries value Folders visible
cn Chinese only
en English only
all Both
(not set) English (default)

When inviting a new user, choose the appropriate template from the invitation presets — the jellyfin_libraries attribute is set there and flows through automatically.

Direct play only

All users have transcoding and remuxing disabled — streams must be played directly. This is enforced by jellyfin-librarian on every login alongside the folder policy.


User Onboarding

New users are onboarded via an invitation link — no manual Jellyfin configuration needed.

graph LR
    A[Admin creates invitation] -->|shares link| B[User registers]
    B --> C[Authentik account created]
    C -->|LDAP| D[User logs into Jellyfin]
    D -->|webhook| E[jellyfin-librarian]
    E -->|sets library policy| D

    style E fill:#27ae60,stroke:#1e8449,color:#fff
Hold "Alt" / "Option" to enable pan & zoom
  1. Admin creates an invitation in Authentik with the appropriate jellyfin_libraries attribute — see Authentik → User Onboarding
  2. User registers via the invitation link — account is created and added to jellyfin_user (LDAP) automatically
  3. On first login, jellyfin-librarian reads jellyfin_libraries from Authentik and sets the correct library folders and playback policy
{"groups": ["jellyfin_user"], "attributes.jellyfin_libraries": "cn"}
{"groups": ["jellyfin_user"], "attributes.jellyfin_libraries": "en"}
{"groups": ["jellyfin_user"], "attributes.jellyfin_libraries": "all"}

No attribute needed for English access

If jellyfin_libraries is not set, jellyfin-librarian defaults to en. Omit the attribute for English-only users.