Jellyfin
Jellyfin is a fully open-source, fork-of-Emby media server: video, music, and photo streaming to any device, with no account, no telemetry, and no licence wall. In this homelab it sits on top of an NFS share from TrueNAS (read-only media library) and a Longhorn-encrypted PVC (storage component) for its own config and metadata, exposed via Envoy Gateway on jellyfin.web.kueber.eu.
Why Jellyfin
- No account wall. Plex requires a Plex.tv account and brokers connections through their servers; Jellyfin is fully local and works without any external service.
- Truly free. Plex Pass and Emby Premiere paywall features (hardware transcoding, mobile sync, live TV) that Jellyfin ships in the base build.
- Client ecosystem is wide enough. Native apps for Android TV, iOS, Android, web, plus first-class support from Infuse, Findroid, Streamyfin, and (via jellycon) Kodi.
- Plays well with the storage layout. TrueNAS exports the media share over NFS, Jellyfin mounts it read-only, and writes only its config + metadata into the cluster — keeps the per-app PVC small and easy to back up.
Alternatives considered
| Option | Hosted | Self-hosted | Why not |
|---|---|---|---|
| Plex | partial | ✓ | Account required; Plex Pass paywalls hardware transcoding |
| Emby | ✓ | Closed-source after the Jellyfin fork; key features need Premiere | |
| Netflix / streaming services | ✓ | Library churn; nothing offline; no control over codecs or quality |
Installation
The Jellyfin install is straightforward — one Deployment, two volumes, one HTTPRoute — but every bit of it leans on a primitive defined elsewhere:
- Single
Deploymentin thejellyfinnamespace, image pinned by digest. Renovate keeps the tag fresh. - Storage split across two volumes. A 150Gi
ReadWriteOncePVC on thelonghorn-encryptedstorage class (storage resource) for Jellyfin's own config and metadata, annotatedk8up.io/backup: "true"so the backups component picks it up. The media library itself is an NFS PV pointing at TrueNAS, mounted read-only. - Routing via
HTTPRouteto the public Envoy Gateway listener — TLS terminated at the edge by cert-manager on the gateway level, not in the pod. - No in-cluster database. Jellyfin keeps its state in an embedded SQLite next to the config PVC, so there's no CNPG dependency.
- Image: linuxserver.io build. The container expects
PUID/PGIDto align ownership of the NFS mount and the config PVC; that means it runs asrunAsUser: 0with achownat startup rather than as a non-root user. It's the pragmatic trade for the linuxserver build's PUID/PGID handling.
Administration
- Logging in for the first time. The first browser hit on a fresh deploy launches the setup wizard — pick a username, point Jellyfin at the NFS-mounted media paths, and let it scan. The scan is the long step on first run.
- Adding a library. Admin Dashboard → Libraries → Add Media Library. Paths are the in-container mount points (
/data/movies,/data/shows), not the host paths. - Hardware transcoding. Talos exposes the integrated Intel GPU via the
intel-gpu-pluginDaemonSet; Jellyfin's Playback → Hardware acceleration picks it up as VA-API. Soft-fallback to software transcoding if the GPU isn't scheduled on the node. - SSO is not wired up. Jellyfin's own user store handles auth. The SSO-Auth plugin is an option for delegating to Keycloak, but the value is marginal for the handful of accounts on this server.
- Upgrades. Digest-pinned image; Renovate auto-merges patch + digest bumps per the Renovate policy. Minor/major bumps need a human read — releases occasionally include schema migrations on the first start after upgrade.
- Backups.
k8up.io/backup: "true"on the config PVC is the only knob; the backups component schedules the restic snapshot to Hetzner S3. The media library on TrueNAS is not backed up via k8up — see Topics → Backups end-to-end for the full storage-tier story.
Usage
- Browser, mobile apps, and TV apps all just point at
https://jellyfin.web.kueber.eu. - Direct-play whenever possible. Most modern clients (Infuse, Streamyfin, the Android TV app) handle H.264 / H.265 / AV1 natively, so the server hands the file off as-is. Only the lowest-common-denominator clients trigger transcoding.
- Offline downloads. The official mobile apps support sync to local storage; useful before flights, less so day-to-day.
- Metadata. Jellyfin pulls from TheMovieDB / TheTVDB at scan time and caches in the config PVC. Re-scanning a library re-fetches missing metadata but does not overwrite manual edits.
Cluster Deployment
Jellyfin — Talos cluster
Cluster-specific notes only. General product info, "why we use it", and alternatives live in docusaurus/docs/apps/jellyfin.mdx.
Deviations from defaults
Defaults live in docusaurus/docs/apps/jellyfin.mdx — document anything this cluster does differently here, with a one-line reason.
- Image:
linuxserver/jellyfin:10.11.11@sha256:c123ef2f82195e377d8ca3df275f13f9dfa5c6e61b195958662b42b5e54362ab
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app: jellyfin
name: jellyfin
namespace: jellyfin
spec:
replicas: 1
selector:
matchLabels:
app: jellyfin
homepage: active
ingress: public
strategy:
rollingUpdate: null
type: Recreate
template:
metadata:
labels:
app: jellyfin
homepage: active
ingress: public
spec:
containers:
- env:
- name: PUID
value: '0'
- name: GUID
value: '0'
image: linuxserver/jellyfin:10.11.11@sha256:c123ef2f82195e377d8ca3df275f13f9dfa5c6e61b195958662b42b5e54362ab
name: jellyfin
ports:
- containerPort: 8096
name: web
protocol: TCP
readinessProbe:
failureThreshold: 1
httpGet:
path: /
port: 8096
initialDelaySeconds: 2
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2
resources:
limits:
gpu.intel.com/i915: 1
memory: 4162Mi
requests:
cpu: 135m
gpu.intel.com/i915: 1
memory: 4162Mi
volumeMounts:
- mountPath: /config
name: jellyfin-config
- mountPath: /data
name: jellyfin-data
securityContext:
fsGroup: 104
seccompProfile:
type: RuntimeDefault
volumes:
- name: jellyfin-config
persistentVolumeClaim:
claimName: jellyfin-config
- name: jellyfin-data
persistentVolumeClaim:
claimName: jellyfin-truenas-nfs-videos