<?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>Pingvin-Share – Serverküche</title><link>https://serverkueche.de/tags/pingvin-share/</link><description>Pingvin-Share – 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>Thu, 29 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/pingvin-share/index.xml" rel="self" type="application/rss+xml"/><item><title>Pingvin Share X: große Dateien teilen ohne WeTransfer</title><link>https://serverkueche.de/tutorials/pingvin-share-dateien-teilen/</link><pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/pingvin-share-dateien-teilen/</guid><description>Dateien selbst hosten statt hochladen: Pingvin Share X 2.0 hinter Traefik, mit Ablaufdatum, Passwort und Abrufzähler – plus den Einstellungen, die zählen.</description><content:encoded><![CDATA[<p>Ein 800-MB-Video an eine Kollegin schicken – und dafür einen fremden Dienst benutzen, der die Datei
für dich behält, so lange er mag. Es geht auch anders: ein Upload-Feld auf deinem eigenen Server,
ein Link mit Ablaufdatum, danach ist die Datei weg.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Wir betreiben <strong>Pingvin Share X 2.0.0</strong> hinter Traefik. Du lädst Dateien hoch, bekommst einen
kurzen Link, und die Freigabe kann <strong>ablaufen</strong>, ein <strong>Passwort</strong> verlangen und nach einer
festgelegten <strong>Zahl von Abrufen</strong> verschwinden. Wer den Link bekommt, braucht kein Konto und keine
App.</p>
<p>Genauso wichtig ist der zweite Teil: Ein Upload-Dienst im offenen Netz ist eine Einladung, wenn er
falsch konfiguriert ist. Wir schalten deshalb die offene Registrierung ab, begrenzen die Dateigröße
und schauen uns an, wie die Daten tatsächlich auf der Platte liegen.</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>Warum das X im Namen steht
  </p>
  <div class="prose-kitchen text-sm">Das ursprüngliche <strong>Pingvin Share</strong> von stonith404 ist seit <strong>Juni 2025 archiviert</strong> – der
Entwickler konzentriert sich auf sein anderes Projekt und empfiehlt im eigenen README den Fork
<strong>Pingvin Share X</strong> als gepflegte Fortsetzung. Genau den nehmen wir, in der Version 2.0.0 vom
3. Oktober 2026. Findest du im Netz eine Anleitung mit
<code>stonith404/pingvin-share</code>, setzt du unwartete Software auf – für einen Dienst, der öffentlich
Uploads annimmt, ist das keine gute Idee.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li><a href="/tutorials/reverse-proxy-traefik/">Traefik als Reverse Proxy</a> mit funktionierendem
Let&rsquo;s-Encrypt-Resolver und einer Domain, die auf den Server zeigt</li>
<li>Genug <strong>Plattenplatz</strong> für das, was du teilen willst – die Dateien liegen unkomprimiert auf dem
Server, bis die Freigabe abläuft</li>
<li>Ein aufgeräumtes Verständnis davon, wem du Links schickst; mehr dazu in Schritt 3</li>
</ul>
<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"
     data-track-content data-content-name="Affiliate-Box · /tutorials/pingvin-share-dateien-teilen/" data-content-piece="VPS 1000 G12.5">
  <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">VPS 1000 G12.5</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 128 GB SSD</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 14,50 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Pingvin Share X ist genügsam – entscheidend ist der Plattenplatz, nicht die CPU.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12.5-24m-eu?ref=44083#vps-1000-g12.5-12m-eu" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12.5 · {page}"
   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"><div class="not-prose my-3 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"
     data-voucher-api="vps-1000" data-voucher-msg-empty="Gerade ist für diesen Tarif kein Code frei – nimm den 5,95-€-Code." data-voucher-msg-limit="Für heute sind keine weiteren Codes drin – nimm den 5,95-€-Code oder versuch es morgen." data-voucher-msg-error="Der Code ließ sich gerade nicht abrufen – nimm den 5,95-€-Code."
     data-voucher-hint="Warenkorb vorher leeren – der Code legt den Server selbst hinein.">
  <p class="flex flex-wrap items-center gap-x-2 gap-y-1"><span>💶 <span class="font-semibold">1 Monat gratis</span>:</span>
    <button type="button" data-voucher-reveal data-copy-title="Zum Kopieren klicken"
            class="cursor-pointer rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 hover:ring-2 hover:ring-herb-500/40 dark:bg-slate-800 dark:text-herb-400">Code anzeigen</button>
    <button type="button" data-voucher-next hidden
            class="rounded border border-herb-500/40 px-2 py-0.5 text-xs text-herb-800 hover:bg-white dark:text-herb-400 dark:hover:bg-slate-800">anderer Code</button>
  </p><p class="mt-1 text-xs text-slate-500 dark:text-slate-400" data-voucher-hint-target>
    Einmal einlösbar, gilt für VPS 1000 G12.5.
    <a href="https://www.netcup.com/de/checkout/warenkorb?ref=44083" rel="sponsored noopener" target="_blank"
       data-track-event="Affiliate|netcup: Gutschein einlösen|VPS 1000 G12.5 · {page}"
       class="font-medium text-herb-800 underline underline-offset-2 hover:text-herb-900 dark:text-herb-400">Im Warenkorb einlösen →</a>
  </p><p class="mt-2 flex flex-wrap items-center gap-x-2 gap-y-1 border-t border-herb-500/30 pt-2">
    <span>💶 <span class="font-semibold">5,95 € Gutschein</span> für netcup-Neukunden:</span>
    <button type="button" data-voucher-code data-track-voucher="36nc17844976032"
            title="Zum Kopieren klicken" class="cursor-pointer rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 hover:ring-2 hover:ring-herb-500/40 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</button>
    <span class="text-xs text-slate-500 dark:text-slate-400">immer gültig · nicht für Domains und VPS Lite</span>
  </p><p class="mt-1 text-xs"><a href="/netcup-gutschein/" class="font-medium text-herb-800 underline underline-offset-2 hover:text-herb-900 dark:text-herb-400">Alle netcup-Gutscheine →</a></p>
</div></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-den-stack-anlegen">Schritt 1: Den Stack anlegen</h3>
<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 /opt/pingvin/data/images <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/pingvin</span></span></code></pre></div>
</div>
<p>Die Unterordner legen wir gleich mit an, weil Pingvin sonst beim ersten Start ins Leere greift.</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="c"># /opt/pingvin/compose.yaml</span><span class="w">
</span></span></span><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">pingvin</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">ghcr.io/smp46/pingvin-share-x:v2.0.0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">pingvin</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 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="nt">TRUST_PROXY</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;true&#34;</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">./data:/opt/app/backend/data:rw</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">./data/images:/opt/app/frontend/public/img:rw</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 class="p">[</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">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">traefik.enable=true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">traefik.http.routers.pingvin.rule=Host(`DEINE_DOMAIN`)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">traefik.http.routers.pingvin.entrypoints=websecure</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">traefik.http.routers.pingvin.tls.certresolver=le</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">traefik.http.services.pingvin.loadbalancer.server.port=3000</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><code>TRUST_PROXY: &quot;true&quot;</code> ist der Eintrag, den man leicht übersieht: Ohne ihn protokolliert Pingvin
jeden Zugriff mit der IP von Traefik statt der des Besuchers. Steht <strong>kein</strong> Proxy davor, muss der
Wert <code>false</code> bleiben – sonst darf jeder Client seine Quell-IP selbst behaupten.</p>
<p>Der Image-Tag ist bewusst festgenagelt. Es gibt auch einen <code>:beta</code>-Kanal des Projekts – für einen
Dienst, der fremde Uploads annimmt, ist die stabile Version die richtige Wahl.</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 ps</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">NAME      STATUS
</span></span><span class="line"><span class="cl">pingvin   Up 25 seconds (healthy)</span></span></code></pre></div>
</div>
<p>Das <code>(healthy)</code> kommt vom mitgelieferten Healthcheck – der Container meldet sich also nicht nur als
gestartet, sondern antwortet auch. Ein Blick in die Logs bestätigt den sauberen Start:</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 logs --tail <span class="m">1</span></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">LOG [NestApplication] Nest application successfully started</span></span></code></pre></div>
</div>
<p>Beim ersten Start legt Pingvin vorher die SQLite-Datenbank an und spielt gut 40 Migrationen ein;
das dauert ein paar Sekunden. Optional kann Pingvin hochgeladene Dateien von einem
ClamAV-Container prüfen lassen. Für ein privates Setup, bei dem nur du hochlädst, ist das
verzichtbar; sobald Fremde bei dir ablegen dürfen (siehe Reverse Shares weiter unten), lohnt es
sich.</p>
<p>Prüf von außen, dass die Kette steht:</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">curl -s -o /dev/null -w <span class="s2">&#34;%{http_code}\n&#34;</span> https://DEINE_DOMAIN/</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">200</span></span></code></pre></div>
</div>
<h3 id="schritt-2-das-erste-konto-anlegen--und-die-tür-danach-zumachen">Schritt 2: Das erste Konto anlegen – und die Tür danach zumachen</h3>
<p>Ruf <code>https://DEINE_DOMAIN/auth/signUp</code> auf. <strong>Der erste registrierte Benutzer wird automatisch
Administrator</strong> – es gibt kein Standardpasswort, das man vergessen könnte zu ändern.</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>Jetzt sofort weiterlesen
  </p>
  <div class="prose-kitchen text-sm">Ab Werk ist die Registrierung <strong>offen</strong>. Zwischen deinem eigenen Signup und dem nächsten Schritt
kann sich jeder ein Konto auf deinem Server anlegen und Speicherplatz belegen. Mach den nächsten
Schritt direkt im Anschluss, nicht morgen.</div>
</div>
<h3 id="schritt-3-die-einstellungen-die-wirklich-zählen">Schritt 3: Die Einstellungen, die wirklich zählen</h3>
<p>Unter <strong>Configuration → General</strong> trägst du zuerst die <strong>App URL</strong> ein – also
<code>https://DEINE_DOMAIN</code>. Das ist keine Kosmetik: Aus diesem Wert baut Pingvin die Links, die du
verschickst. Steht dort der Standard <code>http://localhost:3000</code>, bekommen deine Empfänger Links, die
bei ihnen ins Nichts zeigen.</p>
<p>Der wichtigere Teil steht unter <strong>Configuration → Security &amp; Access</strong>:</p>
<p><figure class="my-6"><img src="/tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_e372e7f5fc49fe51.webp" srcset="/tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_d56e89f3b20cf024.webp 480w, /tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_e372e7f5fc49fe51.webp 768w, /tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_b8d56f746386eceb.webp 1200w, /tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_466407bf4b17acb6.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/pingvin-share-dateien-teilen/pv-config-security_hu_3ba8a0cb57720470.webp"
    alt="Die Einstellungsseite „Security &amp; Access“ von Pingvin Share X mit eingeschalteten Secure cookies und abgeschalteter Registrierung." title="Secure cookies an, Allow registration aus – die beiden Schalter, die zählen"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Secure cookies an, Allow registration aus – die beiden Schalter, die zählen</figcaption></figure></p>
<ul>
<li><strong>Allow registration</strong> – aus. Du bist der einzige, der Freigaben anlegt. Danach leitet
<code>/auth/signUp</code> nur noch weiter, und auch die API lehnt neue Konten ab („Registration is not
allowed“).</li>
<li><strong>Secure cookies</strong> – an. Damit setzt Pingvin das <code>Secure</code>-Flag auf seinen Cookies, sie werden
also nie über unverschlüsseltes HTTP übertragen. Das geht nur, weil Traefik davor sauberes HTTPS
liefert.</li>
<li><strong>Allow unauthenticated shares</strong> – ab Werk aus, und das bleibt es. Sonst kann jeder Besucher
Dateien auf deinem Server ablegen.</li>
</ul>
<p>Jede Seite hat ihren eigenen <strong>Save</strong>-Knopf, also vor dem Wechseln speichern. Unter
<strong>Configuration → Share</strong> stehen dann noch zwei Werte, die du bewusst entscheiden solltest:</p>
<ul>
<li><strong>Default share ID length</strong> – Standard 8. Pingvin schreibt selbst dazu: „A value below 8 is not
considered secure.&quot; Der Link <strong>ist</strong> das Passwort, solange du keines setzt; kürzere IDs lassen
sich durchprobieren.</li>
<li><strong>Max size</strong> – Standard 1 GB. Setz das auf einen Wert, den dein Plattenplatz verträgt, und
bedenke, dass mehrere Freigaben gleichzeitig offen sein können.</li>
</ul>
<p>Interessant ist außerdem die <strong>Chunk size</strong> (Standard 10 MB): Pingvin lädt große Dateien in Stücken
hoch. Deshalb funktionieren Multi-Gigabyte-Uploads auch durch einen Reverse Proxy hindurch, ohne
dass du an Timeouts oder Größenlimits schrauben musst.</p>
<h3 id="schritt-4-eine-freigabe-mit-ablauf-passwort-und-abruflimit">Schritt 4: Eine Freigabe mit Ablauf, Passwort und Abruflimit</h3>
<p>Auf <strong>Upload</strong> ziehst du eine Datei ins Feld – danach öffnet sich der Dialog:</p>
<p><figure class="my-6"><img src="/tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_16bbb6dd0ccbfb52.webp" srcset="/tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_3f2f37ed7d674dc4.webp 480w, /tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_16bbb6dd0ccbfb52.webp 768w, /tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_d97cec0277959c61.webp 1200w, /tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_45b719d7296b1063.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/pingvin-share-dateien-teilen/pv-share-optionen_hu_506ebcb20eeda824.webp"
    alt="Der Dialog „Create Share&quot; mit generierter Link-ID, sieben Tagen Ablauf, gesetztem Passwort und einem Abruflimit von fünf." title="Drei unabhängige Bremsen: Ablaufdatum, Passwort und maximale Abrufe"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Drei unabhängige Bremsen: Ablaufdatum, Passwort und maximale Abrufe</figcaption></figure></p>
<p>Die Link-ID wird zufällig erzeugt; über <strong>Generate</strong> bekommst du eine neue, und du kannst sie auch
durch etwas Sprechendes ersetzen – nur eben nicht durch etwas Ratbares. Darunter stehen drei
Begrenzungen, die unabhängig voneinander wirken:</p>
<ul>
<li><strong>Expiration</strong> – nach Ablauf ist die Freigabe weg, standardmäßig nach sieben Tagen. „Permanent
share&quot; gibt es auch; benutz es sparsam, sonst füllt sich die Platte mit Dingen, an die sich
niemand mehr erinnert.</li>
<li><strong>Password protection</strong> – ein zusätzliches Passwort. Verschick es über einen <strong>anderen Kanal</strong> als
den Link, sonst ist es Theater.</li>
<li><strong>Maximum views</strong> – nach der eingestellten Zahl von Abrufen schließt sich die Freigabe. Praktisch
für „genau einmal, genau diese Person&quot;.</li>
</ul>
<p>Ein Klick auf <strong>Share</strong> legt die Freigabe an und zeigt den fertigen Link mit dem Ablaufdatum.</p>
<h3 id="schritt-5-die-empfängersicht--und-die-gegenprobe">Schritt 5: Die Empfängersicht – und die Gegenprobe</h3>
<p>So sieht es aus, wenn jemand den Link ohne Passwort öffnet:</p>
<p><figure class="my-6"><img src="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_d04d4942bc60580e.webp" srcset="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_2fb8499375e9b481.webp 480w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_d04d4942bc60580e.webp 768w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_13b261030214d109.webp 1200w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_78359889a77f279b.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-passwort_hu_971437b3cd7dec9e.webp"
    alt="Die Empfängerseite von Pingvin Share X mit dem Dialog „Password required&quot; über der ausgegrauten Dateiliste." title="Ohne Passwort bleibt die Dateiliste verdeckt"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Ohne Passwort bleibt die Dateiliste verdeckt</figcaption></figure></p>
<p>Dass das nicht nur die Oberfläche ist, zeigt die API. Frag die Freigabe direkt ab, ohne Passwort:</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">curl -s https://DEINE_DOMAIN/api/shares/DEINE_SHARE_ID</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">{&#34;message&#34;:&#34;This share is password protected&#34;,&#34;error&#34;:&#34;share_password_required&#34;,&#34;statusCode&#34;:403}</span></span></code></pre></div>
</div>
<p>Kein Dateiname, keine Größe, keine Liste – der Server gibt vor der Passworteingabe nichts preis.
Nach der Eingabe erscheint der Inhalt:</p>
<p><figure class="my-6"><img src="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_c35bf89a6066241a.webp" srcset="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_70eecd107eae9310.webp 480w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_c35bf89a6066241a.webp 768w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_1d32635d75161fb8.webp 1200w, /tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_a2de7f3a5ea3686d.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/pingvin-share-dateien-teilen/pv-empfaenger-dateien_hu_821a1e30bc2ae5be.webp"
    alt="Die Empfängerseite mit einer Datei namens menue-oktober.txt und 177 Byte Größe, dazu Schaltflächen zum Kopieren des Links, zur Vorschau und zum Herunterladen." title="Nach dem Passwort: Link kopieren, Vorschau oder herunterladen"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Nach dem Passwort: Link kopieren, Vorschau oder herunterladen</figcaption></figure></p>
<p>Einzelne Dateien lassen sich direkt herunterladen, mehrere packt Pingvin auf Wunsch in ein ZIP.</p>
<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>Die Dateien liegen im Klartext
  </p>
  <div class="prose-kitchen text-sm">Das Passwort schützt den <strong>Link</strong>, nicht die <strong>Ablage</strong>. Auf dem Server liegen die Dateien
unverschlüsselt unter <code>data/uploads/shares/&lt;share-id&gt;/&lt;uuid&gt;</code>, eine Textdatei lässt sich dort mit
<code>cat</code> lesen. Wer Zugriff auf den Server oder dein Backup hat, liest alles mit. Für
wirklich vertrauliche Inhalte verschlüsselst du die Datei vorher selbst, etwa mit einem
passwortgeschützten Archiv.</div>
</div>
<h3 id="schritt-6-reverse-shares--wenn-andere-dir-etwas-schicken-sollen">Schritt 6: Reverse Shares – wenn andere dir etwas schicken sollen</h3>
<p>Der Weg zurück ist der eigentlich unterschätzte Teil. Unter <strong>Reverse shares</strong> in deinem Konto
erzeugst du mit einem Klick auf <strong>Create</strong> einen Upload-Link der Form
<code>https://DEINE_DOMAIN/upload/EINE_ID</code>. Den schickst du jemandem, die Person lädt hoch – ohne Konto,
ohne Anmeldung – und die entstehende Freigabe landet bei dir.</p>
<p>Der Dialog hat dieselbe Sorgfalt verdient wie die normale Freigabe. Neben dem Ablaufdatum gibt es
<strong>Max share size</strong>, <strong>Max uses</strong> („The maximum number of times this URL can be used.&quot;) sowie
<strong>Simple mode</strong> und <strong>Public access</strong>. <code>Max uses</code> steht ab Werk auf 1 – lass es dabei, wenn du
genau eine Lieferung erwartest. Jeder höhere Wert (bis 1000) heißt: Bis dahin kann jeder, an den
der Link weitergereicht wird, auf deinem Plattenplatz ablegen. <strong>Public access</strong> ist ab Werk an;
dann kann jeder mit dem Link der entstandenen Freigabe sie auch ansehen. Schaltest du es ab, sehen
sie nur du und die Person, die hochgeladen hat.</p>
<p>Für die Link-Länge gilt hier dasselbe wie oben: Pingvin benutzt die eingestellte
<code>Default share ID length</code> ausdrücklich auch für Reverse Shares. Und weil jetzt fremde Dateien auf
deinem Server landen, ist das der Moment, an dem sich die ClamAV-Anbindung tatsächlich lohnt.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<div class="troubleshoot not-prose">
<p><strong>Die verschickten Links zeigen auf <code>http://localhost:3000</code>.</strong> Die <strong>App URL</strong> unter Configuration → General steht noch auf dem Standardwert. Pingvin kennt seine öffentliche Adresse nicht von allein – der Reverse Proxy sagt sie ihm nicht. Trag <code>https://DEINE_DOMAIN</code> ein und speichere; bereits verschickte Links musst du neu erzeugen.</p>
<p><strong>In den Zugriffsprotokollen steht bei jedem Besucher dieselbe IP.</strong> Das ist die Adresse aus dem Docker-Proxy-Netz, und es fehlt <code>TRUST_PROXY: &quot;true&quot;</code> in der Compose-Datei. Erst damit wertet Pingvin die <code>X-Forwarded-For</code>-Header aus. Setz den Wert aber wirklich nur, wenn ein Proxy davorsteht – ohne einen kann sich sonst jeder Client eine beliebige Quell-IP ausdenken.</p>
<p><strong>Ein großer Upload bricht mittendrin ab.</strong> Prüf zuerst die <strong>Max size</strong> unter Configuration → Share; ab Werk sind das 1 GB, und die Oberfläche sagt es dir schon vor dem Hochladen („Maximum total upload size: 1 GB.&quot;). Bleibt es dabei, ist die <strong>Chunk size</strong> der nächste Hebel: Kleinere Stücke als die voreingestellten 10 MB sind bei wackligen Verbindungen zuverlässiger, größere bei stabilen schneller.</p>
<p><strong>Fremde legen Konten auf deiner Instanz an.</strong> Dann steht <strong>Allow registration</strong> noch auf an – der Auslieferungszustand. Schalte es unter Configuration → Security &amp; Access ab und lösch die fremden Konten unter Administration → User management. Zur Kontrolle: <code>curl -s -o /dev/null -w &quot;%{http_code}\n&quot; https://DEINE_DOMAIN/auth/signUp</code> muss danach <code>307</code> liefern und nicht <code>200</code>.</p>
<p><strong>Nach dem Anmelden wirst du sofort wieder ausgeloggt.</strong> Meist ist <strong>Secure cookies</strong> eingeschaltet, während der Aufruf über <code>http://</code> läuft – dann verwirft der Browser das Cookie. Ruf die Seite über HTTPS auf. Wenn du Pingvin bewusst ohne TLS betreibst, muss der Schalter aus bleiben; die Einstellung sagt das selbst: „If enabled, the site will not function when accessed over HTTP.&quot;</p>

</div>
<p class="mt-3 text-sm text-slate-500 dark:text-slate-400">
  Dein Problem ist nicht dabei?
  <a href="/fehler/" class="font-medium text-paprika-700 hover:underline dark:text-paprika-400">Alle Fehlermeldungen durchsuchen →</a>
</p>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<p><strong>Updates</strong> sind ein Tag-Wechsel. Schau vorher in die Release Notes, weil der Fork aktiv entwickelt
wird und in kurzen Abständen Versionen erscheinen:</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"><span class="nb">cd</span> /opt/pingvin
</span></span><span class="line"><span class="cl">cp -a data data-backup-<span class="k">$(</span>date +%F<span class="k">)</span>
</span></span><span class="line"><span class="cl">sed -i <span class="s1">&#39;s/pingvin-share-x:v2.0.0/pingvin-share-x:vNEUE_VERSION/&#39;</span> compose.yaml
</span></span><span class="line"><span class="cl">docker compose pull <span class="o">&amp;&amp;</span> docker compose up -d
</span></span><span class="line"><span class="cl">docker compose logs --tail <span class="m">5</span></span></span></code></pre></div>
</div>
<p>Die Kopie vorher ist wichtig, weil beim Start Datenbankmigrationen laufen. Ein Update pro Quartal
reicht in der Praxis, sofern nichts Sicherheitsrelevantes gemeldet wird.</p>
<p><strong>Sichern</strong> musst du zwei Dinge, und beide liegen unter <code>data/</code>:</p>
<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">/opt/pingvin/data/pingvin-share.db     # Konten, Freigaben, Einstellungen (SQLite)
</span></span><span class="line"><span class="cl">/opt/pingvin/data/uploads/             # die eigentlichen Dateien</span></span></code></pre></div>
</div>
<p>Hier lohnt sich eine Überlegung, die man bei anderen Diensten nicht anstellt: <strong>Willst du die
Uploads überhaupt sichern?</strong> Der Sinn der Sache ist, dass die Dateien nach dem Ablaufdatum
verschwinden. Ein Backup, das sie festhält, macht genau das rückgängig – und weil sie
unverschlüsselt liegen, wandern sie im Klartext in dein Backup-Ziel. Für die meisten reicht es, die
Datenbank zu sichern und die Uploads bewusst wegzulassen. Wenn du beides mitnimmst, gehört das
Backup verschlüsselt, so wie es
<a href="/tutorials/backups-mit-restic/">Restic</a> ohnehin macht.</p>
<p><strong>Aufräumen passiert nicht von allein</strong>, wenn du „Permanent share&quot; benutzt. Abgelaufene Freigaben
räumt Pingvin selbst weg; dauerhafte bleiben liegen, bis du sie löschst. Ein Blick alle paar Monate
auf <code>du -sh /opt/pingvin/data/uploads</code> sagt dir, ob sich etwas angesammelt hat.</p>
<p><strong>Realistischer Aufwand:</strong> Nach dem Aufsetzen fast nichts – ein Update pro Quartal und der
gelegentliche Blick auf den Plattenplatz. Der einzige Punkt, der Disziplin braucht, ist der
Umgang mit den Links: Jeder verschickte Link ist ein Zugang, und anders als ein Passwort lässt er
sich nicht zurückrufen. Dafür gibt es das Ablaufdatum.</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>Noch privater
  </p>
  <div class="prose-kitchen text-sm">Wenn Pingvin nur für dich und ein paar Bekannte da ist, muss es nicht im offenen Netz stehen. Hinter
einer IP-Beschränkung oder komplett im VPN ist der Dienst von außen unsichtbar – das Muster dafür
steht in <a href="/tutorials/interne-dienste-nur-im-vpn/">Dienste nur im VPN erreichbar machen</a>. Für
Freigaben an Außenstehende brauchst du dann allerdings weiterhin den öffentlichen Weg.</div>
</div>
]]></content:encoded></item></channel></rss>