<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Jellyfin – Serverküche</title><link>https://serverkueche.de/tags/jellyfin/</link><description>Jellyfin – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Tue, 21 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/jellyfin/index.xml" rel="self" type="application/rss+xml"/><item><title>Jellyfin selbst hosten: dein eigener Medienserver hinter Traefik</title><link>https://serverkueche.de/tutorials/jellyfin-medienserver/</link><pubDate>Tue, 21 Jul 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/jellyfin-medienserver/</guid><description>Jellyfin mit Docker hinter Traefik aufsetzen: deine Filme, Serien und Musik streamen – mit HTTPS und der Mediathek auf netcups Local Block Storage.</description><content:encoded><![CDATA[<p>Netflix, Spotify und Google Fotos in einem – nur auf deinem eigenen Server und ohne
monatliche Gebühr: <strong>Jellyfin</strong> 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 <strong>Local Block Storage</strong>, damit dir der Platz nicht ausgeht.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Am Ende läuft <strong>Jellyfin 10.11</strong> als Container auf deinem Server, erreichbar unter
<code>https://jellyfin.DEINE_DOMAIN</code> 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.</p>
<p>Die eigentliche Herausforderung bei einem Medienserver ist <strong>Speicherplatz</strong> – eine
Filmsammlung sprengt die kleine System-SSD eines VPS schnell. Deshalb binden wir netcups
<strong>Local Block Storage</strong> ein: eine zusätzliche, lokale Festplatte, die im Server wie ein
normales Laufwerk erscheint und auf der die Mediathek liegt.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Ehrlich zum Transcoding
  </p>
  <div class="prose-kitchen text-sm">Jellyfin rechnet Videos bei Bedarf live in ein Format um, das dein Endgerät versteht
(<strong>Transcoding</strong>) – das kostet <strong>viel CPU</strong>. netcup-Server sind reine CPU-Maschinen <strong>ohne
Grafikkarte</strong>, echtes Hardware-Transcoding (über eine GPU) gibt es dort also <strong>nicht</strong>. Auf
einem Root-Server mit <strong>dedizierten Kernen</strong> (RS 1000) läuft Software-Transcoding für ein,
zwei parallele Streams gut; der Königsweg bleibt aber <strong>Direct Play</strong> – dazu unten mehr.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Ein laufender <strong>Traefik-Reverse-Proxy</strong> mit dem <code>proxy</code>-Netzwerk und dem Resolver <code>le</code> –
siehe <a href="/tutorials/reverse-proxy-traefik/">Reverse Proxy mit Traefik</a>.</li>
<li>Eine Subdomain <code>jellyfin.DEINE_DOMAIN</code> mit DNS-Record auf deine Server-IP – siehe
<a href="/tutorials/domain-mit-server-verbinden/">Domain mit Server verbinden</a>.</li>
<li><strong>Dedizierte CPU-Kerne</strong> 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.</li>
<li>Optional, aber empfohlen: gebuchter <strong>netcup Local Block Storage</strong> für die Mediathek
(Schritt 2). Ohne ihn legst du die Medien einfach in einen Ordner auf der System-Disk –
bis der Platz ausgeht.</li>
<li>Ein paar <strong>eigene</strong> Medien-Dateien (Filme/Serien/Musik), die du hosten darfst.</li>
</ul>
<p>Ob dein Setup wirklich dedizierte Kerne braucht, zeigt dir der
<a href="/serverempfehlung/">Server-Rechner</a> – bei Transcoding lautet die Antwort meist ja.</p>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">Root-Server RS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 dedizierte Kerne · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 12,79 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Dedizierte Kerne fürs Transcoding – und Local Block Storage lässt sich dazubuchen.</p>
    </div>
    <a href="https://www.netcup.com/de/server/root-server/rs-1000-g12-ip-12m?ref=44083" rel="sponsored noopener" target="_blank"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span>
  <code class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-dns-record-anlegen">Schritt 1: DNS-Record anlegen</h3>
<p>Lege <code>jellyfin.DEINE_DOMAIN</code> an (A/AAAA auf deine Server-IP) und prüfe, dass er auflöst:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dig +short jellyfin.DEINE_DOMAIN</span></span></code></pre></div>
</div>
<p>Es muss deine Server-IP zurückkommen – sonst holt Traefik später kein Zertifikat.</p>
<h3 id="schritt-2-netcup-local-block-storage-einbinden">Schritt 2: netcup Local Block Storage einbinden</h3>
<p>Der <strong>Local Block Storage</strong> ist zusätzlicher Speicher, den du im netcup-Kundenkonto zu
deinem Server dazubuchst. Anders als der netzgebundene <strong>Storage Space</strong> anderer Anbieter (der per NFS
angebunden wird und langsamer ist) erscheint er im Server als <strong>ganz normale lokale
Festplatte</strong> – ideal für eine Mediathek, weil schnell und beliebig partitionierbar.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Kein Block Storage gebucht?
  </p>
  <div class="prose-kitchen text-sm">Dann überspring diesen Schritt und lege die Mediathek einfach unter <code>~/jellyfin/media</code> 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.</div>
</div>
<p>Sieh dir zuerst an, welche Festplatten der Server kennt:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo fdisk -l</span></span></code></pre></div>
</div>
<p>Die System-Disk ist typischerweise <code>/dev/sda</code> (bzw. <code>/dev/vda</code>). Der neue Block Storage
taucht als <strong>zusätzliches</strong> Gerät auf, meist <code>/dev/vdb</code> – erkennbar an der Größe, die du
gebucht hast.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-paprika-400 bg-paprika-50 dark:border-paprika-700 dark:bg-paprika-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🔥</span>Erst prüfen, dann partitionieren
  </p>
  <div class="prose-kitchen text-sm">Die Gerätenamen können je nach Server abweichen. Partitionierst du versehentlich die
<strong>System-Disk</strong>, ist dein Server hinüber. Ordne das Gerät eindeutig über die <strong>Größe</strong> zu,
bevor du fortfährst. Im Zweifel vorher einen <a href="/tutorials/netcup-snapshots-scp/">Snapshot</a>
anlegen.</div>
</div>
<p>Lege eine Partition auf der neuen Disk an (hier <code>/dev/vdb</code>):</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo cfdisk /dev/vdb</span></span></code></pre></div>
</div>
<p>Wähle bei der Abfrage <strong>gpt</strong> (der moderne Standard – <strong>dos</strong>/MBR kann maximal 2 TiB
adressieren, Mediatheken wachsen gern darüber hinaus), dann <strong>New</strong>, nimm die volle
Größe, und schreib die Tabelle mit <strong>Write</strong> (tippe <code>yes</code>), danach <strong>Quit</strong>. Es entsteht
die Partition <code>/dev/vdb1</code>. Formatiere sie mit einem ext4-Dateisystem:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkfs.ext4 /dev/vdb1</span></span></code></pre></div>
</div>
<p>Erstelle einen Mount-Punkt und häng die Partition ein:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /mnt/media
</span></span><span class="line"><span class="cl">sudo mount /dev/vdb1 /mnt/media</span></span></code></pre></div>
</div>
<p>Damit die Disk <strong>auch nach einem Reboot</strong> automatisch eingehängt wird, trägst du sie mit
ihrer <strong>UUID</strong> (nicht mit <code>/dev/vdb1</code>, das kann sich ändern) in die <code>/etc/fstab</code> ein. UUID
auslesen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo blkid /dev/vdb1</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/dev/vdb1: UUID=&#34;a1b2c3d4-....&#34; TYPE=&#34;ext4&#34; ...</span></span></code></pre></div>
</div>
<p>Öffne die <code>fstab</code> und häng die Zeile mit <strong>deiner</strong> UUID an:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo nano /etc/fstab</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">UUID=a1b2c3d4-....   /mnt/media   ext4   defaults   0   2</span></span></code></pre></div>
</div>
<p>Prüfe die Einträge, <strong>bevor</strong> du dich auf den Reboot verlässt – ein Tippfehler in der
<code>fstab</code> kann den Bootvorgang blockieren:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo umount /mnt/media <span class="o">&amp;&amp;</span> sudo mount -a <span class="o">&amp;&amp;</span> df -h /mnt/media</span></span></code></pre></div>
</div>
<p>Kommt hier keine Fehlermeldung und zeigt <code>df -h</code> deine neue Disk unter <code>/mnt/media</code>, ist
alles korrekt eingetragen.</p>
<h3 id="schritt-3-projekt-und-medien-ordner-anlegen">Schritt 3: Projekt und Medien-Ordner anlegen</h3>
<p>Leg das Compose-Projekt an – die Konfiguration ist klein und darf auf die System-Disk.
Die Unterordner <code>config</code> und <code>cache</code> legst du dabei gleich mit an, <strong>bevor</strong> der
Container das erste Mal startet: Würde erst der Docker-Daemon sie erzeugen, gehörten
sie <code>root</code> – Jellyfin läuft aber als UID 1000 (siehe Schritt 4) und könnte in sein
eigenes <code>/config</code> nicht schreiben, der Container würde beim ersten Start abstürzen.</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p ~/jellyfin/<span class="o">{</span>config,cache<span class="o">}</span> <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ~/jellyfin</span></span></code></pre></div>
</div>
<p>Und die Ordnerstruktur für die Mediathek auf dem Block Storage. Jellyfin sortiert am besten,
wenn Film, Serie und Musik getrennt liegen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /mnt/media/<span class="o">{</span>filme,serien,musik<span class="o">}</span></span></span></code></pre></div>
</div>
<p>Damit der Jellyfin-Container die Dateien lesen darf, müssen sie deinem Benutzer gehören.
Ermittle deine User- und Gruppen-ID (meist <code>1000</code>) und übereigne den Ordner:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">id -u <span class="o">&amp;&amp;</span> id -g
</span></span><span class="line"><span class="cl">sudo chown -R 1000:1000 /mnt/media</span></span></code></pre></div>
</div>
<p>Kopiere jetzt deine Medien in die passenden Unterordner (per <code>scp</code>, <code>rsync</code> oder einem
SFTP-Client). Für eine saubere Erkennung hilft eine klare Benennung, z. B.
<code>filme/Der Pate (1972)/Der Pate (1972).mkv</code>.</p>
<h3 id="schritt-4-die-composeyaml">Schritt 4: Die compose.yaml</h3>
<p>Jetzt die zentrale Datei. Ersetze <code>jellyfin.DEINE_DOMAIN</code> durch deine Subdomain:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">jellyfin</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">jellyfin/jellyfin:10.11.11</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">user</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;1000:1000&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">JELLYFIN_PublishedServerUrl=https://jellyfin.DEINE_DOMAIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./config:/config</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./cache:/cache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/mnt/media:/media:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.jellyfin.rule=Host(`jellyfin.DEINE_DOMAIN`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.jellyfin.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.jellyfin.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.jellyfin.loadbalancer.server.port=8096&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">proxy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div>
</div>
<p>Was die Zeilen bedeuten:</p>
<ul>
<li><strong><code>image: …:10.11.11</code></strong> – die feste, aktuelle Stable-Version. Kein <code>latest</code> (siehe
„Wartung &amp; Backups&quot;).</li>
<li><strong><code>user: &quot;1000:1000&quot;</code></strong> – Jellyfin läuft mit <strong>deiner</strong> User-/Gruppen-ID, damit es die
Medien lesen kann. Passt du in Schritt 3 andere IDs an, hier ebenfalls ändern.</li>
<li><strong><code>JELLYFIN_PublishedServerUrl</code></strong> – sagt Jellyfin, unter welcher öffentlichen Adresse es
erreichbar ist. Das verhindert, dass App-Links plötzlich auf eine interne IP zeigen.</li>
<li><strong><code>volumes</code></strong>: <code>config</code> (Einstellungen, Nutzer, Metadaten) und <code>cache</code> liegen klein im
Projektordner; die <strong>Mediathek</strong> wird vom Block Storage unter <code>/mnt/media</code> als <code>/media</code>
in den Container gehängt – <strong><code>:ro</code></strong> (read-only), damit Jellyfin deine Originale niemals
verändert.</li>
<li><strong>Die vier Traefik-Labels</strong> sind das bekannte Muster. Neu ist nur der Port: Jellyfin
lauscht auf <strong>8096</strong>, deshalb das <code>loadbalancer.server.port</code>-Label. Ohne es gäbe es einen
<code>502 Bad Gateway</code>.</li>
<li><strong>Kein <code>ports:</code></strong> – Jellyfin ist ausschließlich über Traefik (HTTPS) erreichbar, nicht
direkt aus dem Internet.</li>
</ul>
<p>Starte den Stack und sieh beim Hochfahren zu:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d
</span></span><span class="line"><span class="cl">docker compose logs -f jellyfin</span></span></code></pre></div>
</div>
<p>Beim ersten Start braucht die Zertifikatsausstellung ein paar Sekunden. Sobald im Log
<code>Startup complete</code> erscheint, ist Jellyfin bereit.</p>
<h3 id="schritt-5-der-ersteinrichtungs-assistent">Schritt 5: Der Ersteinrichtungs-Assistent</h3>
<p>Ruf <code>https://jellyfin.DEINE_DOMAIN</code> im Browser auf. Beim allerersten Aufruf führt dich ein
Assistent durch die Grundeinrichtung:</p>
<ol>
<li><strong>Sprache</strong> wählen (Deutsch).</li>
<li>Ein <strong>Administrator-Konto</strong> anlegen – vergib ein <strong>langes, einmaliges Passwort</strong>, denn die
Anmeldeseite steht öffentlich im Netz.</li>
<li><strong>Medienbibliotheken hinzufügen</strong>: Klick „Medienbibliothek hinzufügen&quot;, wähl den Typ
(z. B. <em>Filme</em>), und trag als Ordner den <strong>Container-Pfad</strong> ein – also <code>/media/filme</code>
(nicht <code>/mnt/media/filme</code>, das ist der Pfad auf dem Host!). Wiederhole das für <code>serien</code>
und <code>musik</code>.</li>
<li><strong>Metadaten-Sprache</strong> auf Deutsch stellen, den Rest kannst du übernehmen.</li>
</ol>
<p><figure class="my-6"><img src="/tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_d4871e62b9d9548e.webp" srcset="/tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_c175c82e011baa76.webp 480w, /tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_d4871e62b9d9548e.webp 768w, /tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_f21106abf7192408.webp 1200w, /tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_ffa4d45f4476c0eb.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/jellyfin-medienserver/jellyfin-einrichtung_hu_80b42dcab99913e4.webp"
    alt="Der Jellyfin-Einrichtungsassistent beim ersten Aufruf mit Feldern für Servername und bevorzugte Anzeigesprache" title="Der Einrichtungsassistent beim ersten Aufruf"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Der Einrichtungsassistent beim ersten Aufruf</figcaption></figure></p>
<p>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
<strong>Dashboard → Geplante Aufgaben</strong>. Danach landest du auf der Startseite und siehst deine
Mediathek mit den ersten Titeln:</p>
<p><figure class="my-6"><img src="/tutorials/jellyfin-medienserver/jellyfin-startseite_hu_a28636725ecb72e2.webp" srcset="/tutorials/jellyfin-medienserver/jellyfin-startseite_hu_171649ea37d0066c.webp 480w, /tutorials/jellyfin-medienserver/jellyfin-startseite_hu_a28636725ecb72e2.webp 768w, /tutorials/jellyfin-medienserver/jellyfin-startseite_hu_3d55282d6018ac32.webp 1200w, /tutorials/jellyfin-medienserver/jellyfin-startseite_hu_a5c14a790e02829a.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/jellyfin-medienserver/jellyfin-startseite_hu_96923a1fcf8d59c1.webp"
    alt="Die Jellyfin-Startseite nach dem Setup mit der Bibliothek „Filme&quot; und einem zuletzt hinzugefügten Film" title="Die Startseite mit der ersten Mediathek"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Die Startseite mit der ersten Mediathek</figcaption></figure></p>
<h3 id="schritt-6-jellyfin-hinter-dem-proxy-sauber-konfigurieren">Schritt 6: Jellyfin hinter dem Proxy sauber konfigurieren</h3>
<p>Zwei Einstellungen sorgen dafür, dass Jellyfin hinter Traefik korrekt arbeitet. Öffne
<strong>Dashboard → Netzwerk</strong>:</p>
<p><figure class="my-6"><img src="/tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_e81dece8e7eb8a6c.webp" srcset="/tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_18924d29b16da757.webp 480w, /tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_e81dece8e7eb8a6c.webp 768w, /tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_d6fdf325bbe822ef.webp 1200w, /tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_7676ffd83b6a8a23.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/jellyfin-medienserver/jellyfin-dashboard_hu_9b3dc8d50d292181.webp"
    alt="Das Jellyfin-Administrations-Dashboard mit Server-Version 10.11.11, aktiven Geräten und den Speicherpfaden, links das Menü mit Netzwerk- und Wiedergabe-Einstellungen" title="Das Admin-Dashboard – hier sitzen auch Netzwerk und Wiedergabe"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Das Admin-Dashboard – hier sitzen auch Netzwerk und Wiedergabe</figcaption></figure></p>
<ul>
<li>
<p>Unter <strong>Bekannte Proxys / Known proxies</strong> trägst du das Traefik-Netzwerk ein, damit
Jellyfin die <strong>echte</strong> Client-IP sieht (statt der Container-IP von Traefik). Das Subnetz
ermittelst du mit:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker network inspect proxy --format <span class="s1">&#39;{{ (index .IPAM.Config 0).Subnet }}&#39;</span></span></span></code></pre></div>
</div>
<p>Trag den zurückgegebenen Bereich (z. B. <code>172.19.0.0/16</code>) dort ein.</p>
</li>
<li>
<p><strong>HTTPS</strong>: Da Traefik die Verschlüsselung übernimmt, muss Jellyfin selbst <strong>kein</strong> TLS
machen. Lass die HTTPS-Optionen in Jellyfin leer – alles läuft über den Proxy.</p>
</li>
</ul>
<p>WebSockets (für Live-Updates der Oberfläche) leitet Traefik automatisch weiter, da ist nichts
zu tun.</p>
<h3 id="schritt-7-transcoding-vs-direct-play">Schritt 7: Transcoding vs. Direct Play</h3>
<p>Ob dein Server ins Schwitzen kommt, entscheidet sich hier. Zwei Fälle:</p>
<ul>
<li><strong>Direct Play</strong> – das Endgerät kann die Datei so abspielen, wie sie ist. Der Server
schiebt nur Bytes durch, <strong>fast keine CPU-Last</strong>. Das ist der Idealfall.</li>
<li><strong>Transcoding</strong> – Format, Codec oder Bitrate passen nicht zum Gerät (oder die Leitung ist
zu langsam), also rechnet Jellyfin <strong>live</strong> um. Auf einem netcup-Server passiert das über
die <strong>CPU</strong> – bei einem 4K-Stream kann das einen ganzen Server auslasten.</li>
</ul>
<p>So hältst du die Last niedrig:</p>
<ul>
<li><strong>Passende Formate</strong> bereitstellen: H.264/AAC in einem <code>.mp4</code>/<code>.mkv</code> spielt praktisch jedes
Gerät direkt ab. Exotische Codecs (z. B. bestimmte 4K-HEVC-Tonspuren) erzwingen Transcoding.</li>
<li><strong>Client-Qualität</strong> in der App auf „Original/Direct Play&quot; stellen, wenn die Leitung reicht.</li>
<li>Unter <strong>Dashboard → Wiedergabe</strong> kannst du die Transcoding-Einstellungen und ein Limit für
gleichzeitige Streams setzen.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Hardware-Transcoding braucht eine GPU
  </p>
  <div class="prose-kitchen text-sm">Die in Jellyfin wählbare <strong>Hardwarebeschleunigung</strong> (VAAPI, QSV, NVENC) setzt eine
Grafikeinheit unter <code>/dev/dri</code> voraus. Standard-VPS und -Root-Server bei netcup sind
KVM-Maschinen <strong>ohne</strong> durchgereichte GPU – lass die Hardwarebeschleunigung dort <strong>aus</strong>, sie
würde nur Fehler produzieren. Plane stattdessen mit dedizierten CPU-Kernen und Direct Play.</div>
</div>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<p><strong>Symptom:</strong> <code>502 Bad Gateway</code> beim Aufruf, obwohl der Container läuft.</p>
<p><strong>Ursache &amp; Lösung:</strong> Traefik erreicht den Container, trifft aber den falschen Port. Jellyfin
lauscht auf <strong>8096</strong> – das Label <code>traefik.http.services.jellyfin.loadbalancer.server.port=8096</code>
muss gesetzt sein. Prüfe außerdem, dass Jellyfin im <strong><code>proxy</code>-Netzwerk</strong> hängt.</p>
<p><strong>Symptom:</strong> Die Bibliotheken bleiben leer, obwohl Dateien da sind.</p>
<p><strong>Ursache &amp; Lösung:</strong> Fast immer ein <strong>Rechte-Problem</strong>. Der Container läuft als <code>1000:1000</code>
(Schritt 4), die Medien müssen also diesem Benutzer gehören: <code>sudo chown -R 1000:1000 /mnt/media</code>.
Und: In Jellyfin muss der <strong>Container-Pfad</strong> stehen (<code>/media/filme</code>), nicht der Host-Pfad.
Danach unter <strong>Dashboard → Geplante Aufgaben</strong> „Alle Bibliotheken scannen&quot; starten.</p>
<p><strong>Symptom:</strong> Video ruckelt/puffert, <code>docker stats</code> zeigt Jellyfin bei ~100 % CPU.</p>
<p><strong>Ursache &amp; Lösung:</strong> Es wird <strong>transcodiert</strong>. Unter <strong>Dashboard → Wiedergabe</strong> siehst du im
Aktivitätsmonitor, ob „Transcode&quot; statt „Direct Play&quot; 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.</p>
<p><strong>Symptom:</strong> Nach einem Reboot ist die Mediathek weg und Jellyfin zeigt leere Ordner.</p>
<p><strong>Ursache &amp; Lösung:</strong> Der Block Storage wurde nicht eingehängt – meist ein fehlender oder
falscher <code>fstab</code>-Eintrag (Schritt 2). Prüfe mit <code>df -h /mnt/media</code> und <code>sudo mount -a</code>. Die
Zeile muss die <strong>UUID</strong> verwenden, nicht <code>/dev/vdb1</code>.</p>
<p><strong>Symptom:</strong> Login-Seite lädt, aber die App findet den Server nicht / Links zeigen auf eine
interne Adresse.</p>
<p><strong>Ursache &amp; Lösung:</strong> <code>JELLYFIN_PublishedServerUrl</code> fehlt oder ist falsch. Setz sie in der
<code>compose.yaml</code> auf <code>https://jellyfin.DEINE_DOMAIN</code> und starte mit <code>docker compose up -d</code> neu
(ein <code>restart</code> reicht nicht, damit die Environment-Änderung greift).</p>
<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<ul>
<li><strong>Updates bewusst einspielen.</strong> Der feste Tag (<code>jellyfin:10.11.11</code>) bedeutet: Du
entscheidest, wann aktualisiert wird. Tag hochsetzen → <code>docker compose pull</code> →
<code>docker compose up -d</code>. Vor dem Sprung auf eine neue Hauptversion die
Release-Notes lesen – Datenbank-Migrationen sind nicht immer umkehrbar.</li>
<li><strong>Config sichern, Medien getrennt behandeln.</strong> Das <code>config</code>-Volume (Nutzer, Einstellungen,
Wiedergabe-Status, Metadaten) ist klein und der eigentlich wertvolle Teil – sichere es
<a href="/tutorials/backups-mit-restic/">verschlüsselt off-site mit Restic</a>. Die <strong>Mediathek</strong>
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&quot; einstufst.
Ehrlich: Ein zweites Backup deiner Filmsammlung kostet richtig Speicher.</li>
<li><strong>Plattenplatz überwachen.</strong> Eine Mediathek wächst stetig. Behalte die Belegung im Blick
(<code>df -h /mnt/media</code>) und richte am besten einen Monitor in
<a href="/tutorials/uptime-kuma-monitoring/">Uptime Kuma</a> ein, der Alarm schlägt, bevor der Block
Storage voll ist.</li>
<li><strong>Öffentlich erreichbar = absichern.</strong> Die Anmeldeseite steht im Netz, und Jellyfin
bringt <strong>keine Zwei-Faktor-Authentifizierung</strong> 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.</li>
</ul>
]]></content:encoded></item></channel></rss>