Jellyfin selbst hosten: dein eigener Medienserver hinter Traefik
Jellyfin mit Docker hinter Traefik aufsetzen: deine Filme, Serien und Musik streamen – mit HTTPS und der Mediathek auf netcups Local Block Storage.
Inhaltsverzeichnis
Netflix, Spotify und Google Fotos in einem – nur auf deinem eigenen Server und ohne monatliche Gebühr: Jellyfin streamt deine Film-, Serien- und Musiksammlung an jedes Gerät. In diesem Rezept hängen wir Jellyfin hinter Traefik und legen die Mediathek auf netcups Local Block Storage, damit dir der Platz nicht ausgeht.
Was bauen wir?
Am Ende läuft Jellyfin 10.11 als Container auf deinem Server, erreichbar unter
https://jellyfin.DEINE_DOMAIN mit gültigem HTTPS. Jellyfin ist ein komplett freier
Medienserver (keine Cloud, keine Telemetrie, kein Abo): Du legst deine Dateien ab, Jellyfin
zieht automatisch Cover, Beschreibungen und Metadaten und streamt alles an Browser, Handy,
Smart-TV oder die Jellyfin-App.
Die eigentliche Herausforderung bei einem Medienserver ist Speicherplatz – eine Filmsammlung sprengt die kleine System-SSD eines VPS schnell. Deshalb binden wir netcups Local Block Storage ein: eine zusätzliche, lokale Festplatte, die im Server wie ein normales Laufwerk erscheint und auf der die Mediathek liegt.
Ehrlich zum Transcoding
Voraussetzungen
- Ein laufender Traefik-Reverse-Proxy mit dem
proxy-Netzwerk und dem Resolverle– siehe Reverse Proxy mit Traefik. - Eine Subdomain
jellyfin.DEINE_DOMAINmit DNS-Record auf deine Server-IP – siehe Domain mit Server verbinden. - Dedizierte CPU-Kerne sind für flüssiges Streaming klar im Vorteil (Transcoding). Auf einem geteilten VPS geht es für Direct Play auch, wird bei Umrechnung aber schnell eng.
- Optional, aber empfohlen: gebuchter netcup Local Block Storage für die Mediathek (Schritt 2). Ohne ihn legst du die Medien einfach in einen Ordner auf der System-Disk – bis der Platz ausgeht.
- Ein paar eigene Medien-Dateien (Filme/Serien/Musik), die du hosten darfst.
Ob dein Setup wirklich dedizierte Kerne braucht, zeigt dir der Server-Rechner – bei Transcoding lautet die Antwort meist ja.
Root-Server RS 1000 G12
4 dedizierte Kerne · 8 GB RAM · 256 GB NVMe
ab 12,79 €/Monat
Dedizierte Kerne fürs Transcoding – und Local Block Storage lässt sich dazubuchen.
💶 5 € Gutschein für netcup-Neukunden:
36nc17844976032
(nur Neukunden, keine Domains)
Schritt für Schritt
Schritt 1: DNS-Record anlegen
Lege jellyfin.DEINE_DOMAIN an (A/AAAA auf deine Server-IP) und prüfe, dass er auflöst:
dig +short jellyfin.DEINE_DOMAINEs muss deine Server-IP zurückkommen – sonst holt Traefik später kein Zertifikat.
Schritt 2: netcup Local Block Storage einbinden
Der Local Block Storage ist zusätzlicher Speicher, den du im netcup-Kundenkonto zu deinem Server dazubuchst. Anders als der netzgebundene Storage Space anderer Anbieter (der per NFS angebunden wird und langsamer ist) erscheint er im Server als ganz normale lokale Festplatte – ideal für eine Mediathek, weil schnell und beliebig partitionierbar.
Kein Block Storage gebucht?
~/jellyfin/media an –
alle folgenden Befehle funktionieren genauso, nur der Pfad ist ein anderer. Du kannst den
Block Storage jederzeit später dazunehmen und die Daten umziehen.Sieh dir zuerst an, welche Festplatten der Server kennt:
sudo fdisk -lDie System-Disk ist typischerweise /dev/sda (bzw. /dev/vda). Der neue Block Storage
taucht als zusätzliches Gerät auf, meist /dev/vdb – erkennbar an der Größe, die du
gebucht hast.
Erst prüfen, dann partitionieren
Lege eine Partition auf der neuen Disk an (hier /dev/vdb):
sudo cfdisk /dev/vdbWähle bei der Abfrage gpt (der moderne Standard – dos/MBR kann maximal 2 TiB
adressieren, Mediatheken wachsen gern darüber hinaus), dann New, nimm die volle
Größe, und schreib die Tabelle mit Write (tippe yes), danach Quit. Es entsteht
die Partition /dev/vdb1. Formatiere sie mit einem ext4-Dateisystem:
sudo mkfs.ext4 /dev/vdb1Erstelle einen Mount-Punkt und häng die Partition ein:
sudo mkdir -p /mnt/media
sudo mount /dev/vdb1 /mnt/mediaDamit die Disk auch nach einem Reboot automatisch eingehängt wird, trägst du sie mit
ihrer UUID (nicht mit /dev/vdb1, das kann sich ändern) in die /etc/fstab ein. UUID
auslesen:
sudo blkid /dev/vdb1/dev/vdb1: UUID="a1b2c3d4-...." TYPE="ext4" ...Öffne die fstab und häng die Zeile mit deiner UUID an:
sudo nano /etc/fstabUUID=a1b2c3d4-.... /mnt/media ext4 defaults 0 2Prüfe die Einträge, bevor du dich auf den Reboot verlässt – ein Tippfehler in der
fstab kann den Bootvorgang blockieren:
sudo umount /mnt/media && sudo mount -a && df -h /mnt/mediaKommt hier keine Fehlermeldung und zeigt df -h deine neue Disk unter /mnt/media, ist
alles korrekt eingetragen.
Schritt 3: Projekt und Medien-Ordner anlegen
Leg das Compose-Projekt an – die Konfiguration ist klein und darf auf die System-Disk.
Die Unterordner config und cache legst du dabei gleich mit an, bevor der
Container das erste Mal startet: Würde erst der Docker-Daemon sie erzeugen, gehörten
sie root – Jellyfin läuft aber als UID 1000 (siehe Schritt 4) und könnte in sein
eigenes /config nicht schreiben, der Container würde beim ersten Start abstürzen.
mkdir -p ~/jellyfin/{config,cache} && cd ~/jellyfinUnd die Ordnerstruktur für die Mediathek auf dem Block Storage. Jellyfin sortiert am besten, wenn Film, Serie und Musik getrennt liegen:
sudo mkdir -p /mnt/media/{filme,serien,musik}Damit der Jellyfin-Container die Dateien lesen darf, müssen sie deinem Benutzer gehören.
Ermittle deine User- und Gruppen-ID (meist 1000) und übereigne den Ordner:
id -u && id -g
sudo chown -R 1000:1000 /mnt/mediaKopiere jetzt deine Medien in die passenden Unterordner (per scp, rsync oder einem
SFTP-Client). Für eine saubere Erkennung hilft eine klare Benennung, z. B.
filme/Der Pate (1972)/Der Pate (1972).mkv.
Schritt 4: Die compose.yaml
Jetzt die zentrale Datei. Ersetze jellyfin.DEINE_DOMAIN durch deine Subdomain:
services:
jellyfin:
image: jellyfin/jellyfin:10.11.11
user: "1000:1000"
environment:
- JELLYFIN_PublishedServerUrl=https://jellyfin.DEINE_DOMAIN
volumes:
- ./config:/config
- ./cache:/cache
- /mnt/media:/media:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.DEINE_DOMAIN`)"
- "traefik.http.routers.jellyfin.entrypoints=websecure"
- "traefik.http.routers.jellyfin.tls.certresolver=le"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: trueWas die Zeilen bedeuten:
image: …:10.11.11– die feste, aktuelle Stable-Version. Keinlatest(siehe „Wartung & Backups").user: "1000:1000"– Jellyfin läuft mit deiner User-/Gruppen-ID, damit es die Medien lesen kann. Passt du in Schritt 3 andere IDs an, hier ebenfalls ändern.JELLYFIN_PublishedServerUrl– sagt Jellyfin, unter welcher öffentlichen Adresse es erreichbar ist. Das verhindert, dass App-Links plötzlich auf eine interne IP zeigen.volumes:config(Einstellungen, Nutzer, Metadaten) undcacheliegen klein im Projektordner; die Mediathek wird vom Block Storage unter/mnt/mediaals/mediain den Container gehängt –:ro(read-only), damit Jellyfin deine Originale niemals verändert.- Die vier Traefik-Labels sind das bekannte Muster. Neu ist nur der Port: Jellyfin
lauscht auf 8096, deshalb das
loadbalancer.server.port-Label. Ohne es gäbe es einen502 Bad Gateway. - Kein
ports:– Jellyfin ist ausschließlich über Traefik (HTTPS) erreichbar, nicht direkt aus dem Internet.
Starte den Stack und sieh beim Hochfahren zu:
docker compose up -d
docker compose logs -f jellyfinBeim ersten Start braucht die Zertifikatsausstellung ein paar Sekunden. Sobald im Log
Startup complete erscheint, ist Jellyfin bereit.
Schritt 5: Der Ersteinrichtungs-Assistent
Ruf https://jellyfin.DEINE_DOMAIN im Browser auf. Beim allerersten Aufruf führt dich ein
Assistent durch die Grundeinrichtung:
- Sprache wählen (Deutsch).
- Ein Administrator-Konto anlegen – vergib ein langes, einmaliges Passwort, denn die Anmeldeseite steht öffentlich im Netz.
- Medienbibliotheken hinzufügen: Klick „Medienbibliothek hinzufügen", wähl den Typ
(z. B. Filme), und trag als Ordner den Container-Pfad ein – also
/media/filme(nicht/mnt/media/filme, das ist der Pfad auf dem Host!). Wiederhole das fürserienundmusik. - Metadaten-Sprache auf Deutsch stellen, den Rest kannst du übernehmen.

Nach dem Assistenten scannt Jellyfin die Ordner und lädt Cover und Beschreibungen. Bei großen Sammlungen dauert der erste Scan etwas – den Fortschritt siehst du unter Dashboard → Geplante Aufgaben. Danach landest du auf der Startseite und siehst deine Mediathek mit den ersten Titeln:

Schritt 6: Jellyfin hinter dem Proxy sauber konfigurieren
Zwei Einstellungen sorgen dafür, dass Jellyfin hinter Traefik korrekt arbeitet. Öffne Dashboard → Netzwerk:

Unter Bekannte Proxys / Known proxies trägst du das Traefik-Netzwerk ein, damit Jellyfin die echte Client-IP sieht (statt der Container-IP von Traefik). Das Subnetz ermittelst du mit:
Terminaldocker network inspect proxy --format '{{ (index .IPAM.Config 0).Subnet }}'Trag den zurückgegebenen Bereich (z. B.
172.19.0.0/16) dort ein.HTTPS: Da Traefik die Verschlüsselung übernimmt, muss Jellyfin selbst kein TLS machen. Lass die HTTPS-Optionen in Jellyfin leer – alles läuft über den Proxy.
WebSockets (für Live-Updates der Oberfläche) leitet Traefik automatisch weiter, da ist nichts zu tun.
Schritt 7: Transcoding vs. Direct Play
Ob dein Server ins Schwitzen kommt, entscheidet sich hier. Zwei Fälle:
- Direct Play – das Endgerät kann die Datei so abspielen, wie sie ist. Der Server schiebt nur Bytes durch, fast keine CPU-Last. Das ist der Idealfall.
- Transcoding – Format, Codec oder Bitrate passen nicht zum Gerät (oder die Leitung ist zu langsam), also rechnet Jellyfin live um. Auf einem netcup-Server passiert das über die CPU – bei einem 4K-Stream kann das einen ganzen Server auslasten.
So hältst du die Last niedrig:
- Passende Formate bereitstellen: H.264/AAC in einem
.mp4/.mkvspielt praktisch jedes Gerät direkt ab. Exotische Codecs (z. B. bestimmte 4K-HEVC-Tonspuren) erzwingen Transcoding. - Client-Qualität in der App auf „Original/Direct Play" stellen, wenn die Leitung reicht.
- Unter Dashboard → Wiedergabe kannst du die Transcoding-Einstellungen und ein Limit für gleichzeitige Streams setzen.
Hardware-Transcoding braucht eine GPU
/dev/dri voraus. Standard-VPS und -Root-Server bei netcup sind
KVM-Maschinen ohne durchgereichte GPU – lass die Hardwarebeschleunigung dort aus, sie
würde nur Fehler produzieren. Plane stattdessen mit dedizierten CPU-Kernen und Direct Play.Wenn es nicht funktioniert
Symptom: 502 Bad Gateway beim Aufruf, obwohl der Container läuft.
Ursache & Lösung: Traefik erreicht den Container, trifft aber den falschen Port. Jellyfin
lauscht auf 8096 – das Label traefik.http.services.jellyfin.loadbalancer.server.port=8096
muss gesetzt sein. Prüfe außerdem, dass Jellyfin im proxy-Netzwerk hängt.
Symptom: Die Bibliotheken bleiben leer, obwohl Dateien da sind.
Ursache & Lösung: Fast immer ein Rechte-Problem. Der Container läuft als 1000:1000
(Schritt 4), die Medien müssen also diesem Benutzer gehören: sudo chown -R 1000:1000 /mnt/media.
Und: In Jellyfin muss der Container-Pfad stehen (/media/filme), nicht der Host-Pfad.
Danach unter Dashboard → Geplante Aufgaben „Alle Bibliotheken scannen" starten.
Symptom: Video ruckelt/puffert, docker stats zeigt Jellyfin bei ~100 % CPU.
Ursache & Lösung: Es wird transcodiert. Unter Dashboard → Wiedergabe siehst du im Aktivitätsmonitor, ob „Transcode" statt „Direct Play" steht. Stell die Client-Qualität auf Original, stell exotische Codecs auf ein breit unterstütztes Format um, oder gib dem Server mehr (dedizierte) Kerne.
Symptom: Nach einem Reboot ist die Mediathek weg und Jellyfin zeigt leere Ordner.
Ursache & Lösung: Der Block Storage wurde nicht eingehängt – meist ein fehlender oder
falscher fstab-Eintrag (Schritt 2). Prüfe mit df -h /mnt/media und sudo mount -a. Die
Zeile muss die UUID verwenden, nicht /dev/vdb1.
Symptom: Login-Seite lädt, aber die App findet den Server nicht / Links zeigen auf eine interne Adresse.
Ursache & Lösung: JELLYFIN_PublishedServerUrl fehlt oder ist falsch. Setz sie in der
compose.yaml auf https://jellyfin.DEINE_DOMAIN und starte mit docker compose up -d neu
(ein restart reicht nicht, damit die Environment-Änderung greift).
Wartung & Backups
- Updates bewusst einspielen. Der feste Tag (
jellyfin:10.11.11) bedeutet: Du entscheidest, wann aktualisiert wird. Tag hochsetzen →docker compose pull→docker compose up -d. Vor dem Sprung auf eine neue Hauptversion die Release-Notes lesen – Datenbank-Migrationen sind nicht immer umkehrbar. - Config sichern, Medien getrennt behandeln. Das
config-Volume (Nutzer, Einstellungen, Wiedergabe-Status, Metadaten) ist klein und der eigentlich wertvolle Teil – sichere es verschlüsselt off-site mit Restic. Die Mediathek selbst ist meist zu groß fürs klassische Backup und aus den Original-Datenträgern reproduzierbar; entscheide bewusst, ob du sie sicherst oder als „ersetzbar" einstufst. Ehrlich: Ein zweites Backup deiner Filmsammlung kostet richtig Speicher. - Plattenplatz überwachen. Eine Mediathek wächst stetig. Behalte die Belegung im Blick
(
df -h /mnt/media) und richte am besten einen Monitor in Uptime Kuma ein, der Alarm schlägt, bevor der Block Storage voll ist. - Öffentlich erreichbar = absichern. Die Anmeldeseite steht im Netz, und Jellyfin bringt keine Zwei-Faktor-Authentifizierung mit (auch nicht per offiziellem Plugin). Vergib deshalb konsequent starke Passwörter, deaktiviere ungenutzte Konten – und überlege bei rein privater Nutzung, Jellyfin gar nicht öffentlich, sondern nur über ein VPN erreichbar zu machen.
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken

Immich selbst hosten: dein privates Foto-Backup hinter Traefik
Immich mit Docker hinter Traefik aufsetzen: die selbst gehostete Alternative zu Google Fotos – mit automatischem …

Paperless-ngx selbst hosten: papierloses Büro mit OCR
Paperless-ngx mit Docker hinter Traefik aufsetzen: Dokumente per OCR durchsuchbar archivieren – mit Volltextsuche, Tags …

Nextcloud selbst hosten: deine eigene Cloud hinter Traefik
Nextcloud mit Docker hinter Traefik aufsetzen: eigene Cloud für Dateien, Kalender und Kontakte – mit MariaDB, Redis und …