Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Cloud / Hosting 02.06.2026 · 11 min Lesezeit

Jellyfin mit Docker: eigener Media-Server ohne Abo

So richtest du Jellyfin per Docker Compose als eigenen Media-Server ein: kostenlos, ohne Abo und ohne Cloud-Zwang. Mit copy-paste-fertiger compose.yaml, Erst-Setup-Assistent, Bibliotheken, Benutzern, optionalem Hardware-Transcoding (Intel QSV / NVIDIA NVENC) sowie Update- und Backup-Workflow.

Server-Rack mit Festplatten für Backup-Sicherung

Jellyfin mit Docker macht aus einem kleinen Linux-Server deinen eigenen Media-Server für Filme, Serien und Musik - komplett kostenlos, quelloffen und ohne Abo oder Cloud-Login. Damit ist Jellyfin die naheliegende Plex-Alternative, wenn du deine Mediathek selbst hosten und die Kontrolle über deine Daten behalten willst. Diese Anleitung richtet sich an Mittelstands-Admins und ambitionierte Heimserver-Nutzer und zeigt dir Schritt für Schritt den Weg über Docker Compose: vom Verzeichnis und der compose.yaml über den Erst-Setup-Assistenten und Bibliotheken bis zu Benutzern, optionalem Hardware-Transcoding sowie einem sauberen Update- und Backup-Workflow.

Voraussetzungen

Bevor du startest, sollten ein paar Grundlagen stehen. Jellyfin ist genügsam - für reines Direct-Play reicht eine einfache Maschine, GPU brauchst du nur für flottes Transcoding.

  • Linux-Server: Debian 12 oder Ubuntu 24.04 (nativer Linux-Host). Wichtig: Hardware-Transcoding gibt es auf Docker Desktop für Windows/macOS und in WSL2 nicht - dort fehlt der Zugriff auf /dev/dri.
  • Docker & Docker Compose: aktuelle Docker Engine mit dem Compose-Plugin (docker compose, nicht das alte docker-compose).
  • RAM: rund 1-2 GB als Basis genügen; mehr bei vielen parallelen Streams.
  • Storage: Platz für deine Mediathek plus schnelles Storage (SSD) für den /cache-Ordner - keine SD-Karte oder lahme USB-Platte.
  • GPU (optional): nur für Hardware-Transcoding nötig. Intel mit Quick Sync (QSV) oder NVIDIA ab Maxwell mit Treiber >= 520.56.06 und installiertem nvidia-container-toolkit.
  • Netzwerk: die Server-IP (z. B. 192.168.1.10); optional eine Domain, wenn du später per Reverse-Proxy mit HTTPS von außen zugreifen willst.

Schritt 1: Medien vorbereiten und Benutzer-IDs ermitteln

Die mit Abstand häufigste Fehlerquelle bei Jellyfin im Container sind Berechtigungen. Deshalb klären wir das zuerst. Lege auf dem Host eine saubere Ordnerstruktur für deine Medien an und merke dir die UID und GID des Benutzers, dem die Daten gehören sollen.

# Medienordner anlegen (Beispielstruktur)
sudo mkdir -p /srv/medien/filme /srv/medien/serien /srv/medien/musik

# UID und GID des aktuellen Benutzers anzeigen
id
# Beispielausgabe: uid=1000(marcel) gid=1000(marcel) ...

Diese uid:gid (im Beispiel 1000:1000) trägst du gleich in der compose.yaml unter user: ein. Wichtig für das offizielle Image: Es nutzt nicht die Variablen PUID/PGID - das sind die Variablen des inoffiziellen linuxserver/jellyfin-Images. Beim offiziellen jellyfin/jellyfin setzt du den Container-Benutzer ausschließlich über user:.

Schritt 2: Projektverzeichnis und compose.yaml anlegen

Lege ein eigenes Verzeichnis für den Stack an. Darin landen die compose.yaml und die persistenten Ordner config und cache.

sudo mkdir -p /srv/jellyfin
cd /srv/jellyfin
sudo nano compose.yaml

Hier die vollständige, lauffähige compose.yaml für den Standardbetrieb im Bridge-Modus (ohne GPU). Passe user:, die Medienpfade und die JELLYFIN_PublishedServerUrl an deine Umgebung an. Die Medienordner werden bewusst read-only (:ro) gemountet - dazu unten mehr.

services:
  jellyfin:
    image: jellyfin/jellyfin:10.10.3      # festen Tag pinnen statt latest
    container_name: jellyfin
    user: 1000:1000                        # deine UID:GID aus Schritt 1
    ports:
      - "8096:8096"                        # Web-UI (Pflicht)
      - "7359:7359/udp"                    # Client-Auto-Discovery (optional)
    volumes:
      - ./config:/config                   # Datenbank, Einstellungen, Metadaten
      - ./cache:/cache                     # Transcoding-Temp (schnelles Storage)
      - /srv/medien/filme:/media/filme:ro  # Medien read-only
      - /srv/medien/serien:/media/serien:ro
      - /srv/medien/musik:/media/musik:ro
    environment:
      - JELLYFIN_PublishedServerUrl=http://192.168.1.10:8096
    restart: unless-stopped

Stelle sicher, dass die Ordner config, cache und deine Medienordner dem in user: gesetzten uid:gid gehören - sonst startet Jellyfin nicht oder findet die Medien nicht.

# Ownership setzen (Beispiel UID:GID 1000:1000)
sudo mkdir -p /srv/jellyfin/config /srv/jellyfin/cache
sudo chown -R 1000:1000 /srv/jellyfin/config /srv/jellyfin/cache /srv/medien

Tags pinnen statt latest

Das Image bietet die Tags latest (Stable), X (Major), X.Y (Minor) und X.Y.Z (exakte Version). Auf einem Server ist latest riskant: Ein ungewolltes Major-Update kann eine Datenbank-Migration auslösen. Pinne deshalb einen festen Tag wie 10.10.3 und sichere vor jedem Update den config-Ordner. Wer lieber die GitHub Container Registry nutzt, ersetzt das Image durch ghcr.io/jellyfin/jellyfin:10.10.3.

Schritt 3: Stack starten und Logs prüfen

Starte den Container im Hintergrund und kontrolliere die Logs, ob Jellyfin sauber hochkommt.

# Container starten
docker compose up -d

# Status pruefen
docker compose ps

# Logs verfolgen (mit Strg+C beenden)
docker compose logs -f jellyfin

Sobald in den Logs steht, dass der Server lauscht, ist die Web-UI unter http://SERVER-IP:8096 erreichbar. Falls der Container sofort wieder stoppt, ist fast immer eine falsche Ownership der gemounteten Ordner die Ursache (siehe Troubleshooting).

Schritt 4: Ersteinrichtung über die Web-UI

Jellyfin hat kein Default-Passwort - den ersten Admin legst du selbst im Assistenten an. Öffne im Browser http://SERVER-IP:8096 und gehe den Assistenten der Reihe nach durch:

  1. Sprache der Oberfläche wählen (z. B. Deutsch).
  2. Administrator-Account anlegen: Benutzername und ein starkes Passwort vergeben.
  3. Bibliotheken hinzufügen: pro Bibliothek den Inhaltstyp (Filme, Serien oder Musik) wählen und den passenden Ordnerpfad im Container angeben - also /media/filme, /media/serien bzw. /media/musik.
  4. Bevorzugte Metadaten-Sprache und Region festlegen.
  5. Netzwerk: Remote-Zugriff erlauben (oder bewusst nicht). Lass das UPnP-Portmapping deaktiviert - öffne keine Ports automatisch zum Internet.

Nach Abschluss landest du im Dashboard. Stoße für jede Bibliothek einen ersten Metadaten-Scan an, damit Cover und Beschreibungen geladen werden.

Metadaten-Anbieter

Jellyfin nutzt kostenlose Anbieter: TheMovieDb (TMDb) für Filme und Serien, TheTVDB zusätzlich für Serien sowie MusicBrainz und AudioDb für Musik. Du kannst die Anbieter pro Bibliothek in den Bibliothekseinstellungen auswählen und ihre Reihenfolge sortieren - so legst du fest, welche Quelle Vorrang hat.

Schritt 5: Benutzer, Berechtigungen und Clients

Lege weitere Konten unter Dashboard > Benutzer an. Pro Benutzer steuerst du den Zugriff auf einzelne Bibliotheken sowie Wiedergabe-, Transcoding-, Download- und Admin-Rechte. Mit den Inhaltssperren (Parental Controls) blendest du für bestimmte Konten Inhalte ab einer Altersfreigabe aus.

Zum Streamen gibt es offizielle Apps für Android, Android TV, Fire TV, iOS und Roku sowie die Web-UI im Browser. Für Smart-TVs stehen Apps für LG webOS und Samsung Tizen bereit; dazu kommen Drittanbieter-Clients wie Findroid oder Streamyfin. In jeder App gibst du einfach die Server-Adresse http://SERVER-IP:8096 ein und meldest dich mit deinem Jellyfin-Konto an - kein Abo, keine Cloud-Pflicht.

Schritt 6: Hardware-Transcoding aktivieren (optional)

Für reines Direct-Play, bei dem der Client das Format nativ abspielt, brauchst du keine GPU - die CPU reicht völlig. Erst wenn Jellyfin Streams umrechnen muss (mehrere gleichzeitige Streams oder 4K-Wandlung), beschleunigt eine GPU das deutlich. Beachte: Auf Docker Desktop für Windows/macOS und in WSL2 ist Hardware-Transcoding nicht verfügbar - du brauchst einen nativen Linux-Host.

Variante A: Intel Quick Sync (QSV)

Prüfe zuerst, ob die Render-Geräte auf dem Host vorhanden sind, und ermittle die GID der render-Gruppe.

# GPU-Geraete pruefen (sollte card0 und renderD128 zeigen)
ls -la /dev/dri/

# GID der render-Gruppe ermitteln
getent group render | cut -d: -f3
# Beispielausgabe: 122

Ergänze im jellyfin-Service der compose.yaml die folgenden Blöcke. Das offizielle Image bringt die nötigen Intel-Media-Treiber und OpenCL bereits mit; QSV wird gegenüber VAAPI bevorzugt.

    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
    group_add:
      - "122"   # GID der render-Gruppe vom Host (deinen Wert eintragen)

Variante B: NVIDIA NVENC

Das Jellyfin-Image enthält keine NVIDIA-Treiber. Auf dem Host müssen der proprietäre Treiber (>= 520.56.06) und das nvidia-container-toolkit installiert sein; danach Docker neu starten. Unterstützt werden GPUs ab der Maxwell-Architektur.

    runtime: nvidia
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Prüfe nach dem Neustart des Stacks, ob die GPU im Container sichtbar ist:

docker exec -it jellyfin nvidia-smi

In beiden Fällen aktivierst du das Hardware-Transcoding anschließend unter Dashboard > Wiedergabe > Transcoding und wählst dort die passende Beschleunigung (Intel QSV bzw. NVIDIA NVENC).

Schritt 7: DLNA und network_mode host (optional)

Im Standard-Bridge-Modus funktioniert DLNA nicht. Wenn du DLNA bzw. die volle Auto-Discovery im Heimnetz brauchst, betreibe den Container mit network_mode: host. Dann entfällt der ports:-Block, weil der Container direkt am Host-Netzwerk hängt. Achtung: Das kann mit anderen Diensten auf denselben Ports kollidieren - bewusst entscheiden.

services:
  jellyfin:
    image: jellyfin/jellyfin:10.10.3
    container_name: jellyfin
    network_mode: host          # noetig fuer volles DLNA/Discovery
    user: 1000:1000
    volumes:
      - ./config:/config
      - ./cache:/cache
      - /srv/medien:/media:ro
    restart: unless-stopped

Schritt 8: Reverse-Proxy und HTTPS

Der Remote-Zugriff ist bei Jellyfin standardmäßig aktiv. Stelle den Server trotzdem nicht ungeschützt ins Internet. Die offizielle Empfehlung lautet: einen Reverse-Proxy mit HTTPS davorschalten, statt Port 8096 direkt freizugeben. Der Proxy terminiert TLS und reicht die Anfragen intern an http://SERVER-IP:8096 weiter.

Damit Jellyfin die Clients auf die richtige öffentliche Adresse verweist, setzt du beim Betrieb hinter einem Proxy die JELLYFIN_PublishedServerUrl auf deine Domain - etwa https://jellyfin.DEINE-DOMAIN.de. Wie du einen nginx-Reverse-Proxy mit TLS aufsetzt, zeigt die verlinkte Anleitung am Ende dieses Artikels. UPnP-Portmapping lässt du dabei deaktiviert.

Schritt 9: Update- und Backup-Workflow

Updates laufen mit Docker Compose in zwei Schritten: neues Image ziehen, dann den Container neu erstellen. Sichere vorher den config-Ordner.

# Update einspielen
docker compose pull        # neues Image ziehen (zuvor Tag in compose.yaml anpassen)
docker compose up -d       # Container mit neuem Image neu erstellen
docker image prune -f      # alte, ungenutzte Images aufraeumen

Beim Backup zählt vor allem ein Verzeichnis: config enthält Datenbank, Einstellungen und den Metadaten-Cache. Stoppe den Container für ein konsistentes Backup kurz, sichere den Ordner und starte ihn wieder.

cd /srv/jellyfin
docker compose stop jellyfin
tar czf jellyfin-config-backup.tar.gz -C /srv/jellyfin config
docker compose start jellyfin

Den cache-Ordner musst du nicht sichern - er enthält nur temporäre Transcoding-Daten und wird bei Bedarf neu erzeugt.

Troubleshooting

  • Container startet nicht / findet keine Medien: fast immer falsche Ownership. Die Ordner config, cache und die Medienordner müssen dem in user: gesetzten uid:gid gehören. Prüfe mit ls -la und korrigiere per chown. Verwende beim offiziellen Image nicht PUID/PGID.
  • Host-Verzeichnisse werden überschrieben: Der Entrypoint des offiziellen Images ändert die Ownership von /config und /media auf den gesetzten Benutzer. Mounte Medienordner deshalb immer mit :ro und wähle die Pfade sorgfältig.
  • DLNA funktioniert nicht: im Bridge-Modus nicht möglich. Nutze network_mode: host (siehe Schritt 7) - aber Port-Kollisionen beachten.
  • Kein Hardware-Transcoding: auf Docker Desktop (Windows/macOS) und WSL2 generell nicht verfügbar. Bei Intel ist meist eine falsche render-GID in group_add schuld - GID mit getent group render | cut -d: -f3 prüfen (kann je nach Distro auch video oder input heißen). Bei NVIDIA fehlen oft Host-Treiber oder das nvidia-container-toolkit.
  • Transcoding ruckelt / Flash nutzt sich ab: /cache liegt auf langsamem Storage (SD-Karte/USB). Auf eine schnelle SSD bzw. ein lokales Volume umstellen.
  • Ungewolltes Major-Update: image: latest kann DB-Migrationen auslösen. Festen Tag pinnen und vor jedem Update config sichern.

Häufige Fragen

Ist Jellyfin wirklich komplett kostenlos und ohne Abo?

Ja. Jellyfin ist freie, quelloffene Software ohne Abo, ohne Cloud-Login und ohne Premium-Sperren. Es ist damit die klassische Plex-Alternative, wenn du deine Mediathek vollständig selbst hosten willst. Du brauchst nur einen Server, auf dem Docker läuft.

Welche Ports muss ich öffnen?

Pflicht ist nur 8096/TCP für die Web-UI. Optional kommen 7359/UDP für die Client-Auto-Discovery, 8920/TCP für optionales HTTPS und 1900/UDP für DLNA hinzu. Für volles DLNA brauchst du network_mode: host.

Warum sollen die Medienordner read-only gemountet werden?

Weil der Entrypoint des offiziellen Images die Ownership der gemounteten Verzeichnisse auf den gesetzten Benutzer ändert. Mit :ro kann der Container deine Host-Medien nicht umschreiben - Jellyfin braucht ohnehin nur Lesezugriff auf die Mediathek.

Brauche ich zwingend eine GPU?

Nein. Für Direct-Play, bei dem der Client das Format direkt abspielt, reicht die CPU vollkommen aus. Eine GPU lohnt sich erst für flottes Transcoding - etwa mehrere parallele Streams oder die Wandlung von 4K-Material.

Wie aktualisiere ich Jellyfin sicher?

Passe den Image-Tag in der compose.yaml an, sichere den config-Ordner und führe dann docker compose pull gefolgt von docker compose up -d aus. Mit docker image prune -f räumst du alte Images auf. Durch das Pinnen eines festen Tags vermeidest du überraschende Major-Updates.

Kann ich Jellyfin gefahrlos aus dem Internet erreichbar machen?

Nicht direkt. Stelle Port 8096 nicht offen ins Internet, sondern setze einen Reverse-Proxy mit HTTPS davor und lass UPnP-Portmapping deaktiviert. Setze außerdem die JELLYFIN_PublishedServerUrl auf deine öffentliche Domain.

Fazit

Mit Docker Compose ist Jellyfin in wenigen Minuten als eigener Media-Server eingerichtet - kostenlos, quelloffen und ohne Abo oder Cloud-Zwang. Der Kern ist eine schlanke compose.yaml mit Port 8096, persistenten Volumes für config und cache sowie read-only gemounteten Medienordnern. Den Rest erledigt der Setup-Assistent im Browser: Admin-Account, Bibliotheken, Metadaten und Benutzer. Wer mehrere Streams oder 4K wandeln will, ergänzt optional Intel QSV oder NVIDIA NVENC auf einem Linux-Host. Achte auf saubere Berechtigungen, pinne einen festen Image-Tag, sichere regelmäßig den config-Ordner und schalte für den Zugriff von außen einen Reverse-Proxy mit HTTPS davor - dann hast du einen wartungsarmen, datensouveränen Media-Server.

Weiterführende Anleitungen und Quellen

Quellen: Jellyfin Docs - Container/Docker Installation, Jellyfin Docs - Setup Wizard, Jellyfin Docs - Intel QSV Hardware Acceleration und Jellyfin Docs - NVIDIA NVENC Hardware Acceleration.