PrivateBin mit Docker Compose: verschlüsselter Pastebin für Zugangsdaten
PrivateBin verschlüsselt Texte im Browser, der Server speichert nur Chiffretext und der Schlüssel steht allein im Link. Die Anleitung zeigt den Betrieb mit dem offiziellen Docker-Image: schreibgeschütztes Dateisystem, Konfiguration, HTTPS-Pflicht, Ablauf und Burn after reading, Backup und Restore, Updates und die im Test provozierten Fehler.

Zugangsdaten per E-Mail, Passwörter im Teams-Chat, API-Schlüssel im Ticketsystem: In vielen Firmen landen Geheimnisse dauerhaft in Postfächern und Verläufen, weil es keinen bequemen Weg gibt, sie einmalig und verschlüsselt zu übergeben. PrivateBin löst genau diesen Teil. Der Text wird im Browser verschlüsselt, der Server speichert nur Chiffretext, und der Schlüssel steht ausschließlich im Link hinter dem #. Mit Ablaufzeit und der Option, das Dokument nach dem ersten Lesen zu löschen, verschwindet das Geheimnis wieder.
Diese Anleitung zeigt den Betrieb mit dem offiziellen Image privatebin/nginx-fpm-alpine und Docker Compose: gehärtete compose.yaml mit schreibgeschütztem Root-Dateisystem, eine kommentierte conf.php, HTTPS über einen Reverse Proxy, Backup und Restore, Updates sowie die typischen Fehler. PrivateBin ist mit 8616 GitHub-Sternen (GitHub-API, Stand 26.09.2026) ein etabliertes Projekt, zuletzt aktiv am 24.09.2026, aktuelles Release 2.0.6 vom 08.08.2026.
Nutzen und Grenzen von PrivateBin
PrivateBin ist ein minimalistischer Pastebin nach dem Zero-Knowledge-Prinzip. Laut Projektdokumentation verschlüsselt der Browser Text, Dateianhänge, Kommentare und Kommentar-Nicknamen mit AES-256 im GCM-Modus, bevor irgendetwas an den Server geht. Der Schlüssel besteht aus 32 Zufallsbytes, wird Base58-kodiert und bildet das Fragment der URL hinter dem #. Browser senden das Fragment nicht an den Server, deshalb sieht der Betreiber weder Schlüssel noch Klartext.
Für Admins und KMU ergeben sich daraus klare Einsatzfelder:
- Erstpasswörter für neue Mitarbeitende übergeben, mit Ablauf nach einem Tag und Löschung nach dem ersten Lesen.
- WLAN-Schlüssel, Recovery-Codes oder API-Tokens an Dienstleister weitergeben, ohne dass sie im Mailarchiv liegen.
- Log-Auszüge oder Konfigurationsschnipsel mit sensiblen Hostnamen im Team teilen.
- Zusätzlich ein Passwort setzen, das über einen zweiten Kanal (Telefon, Signal) mitgeteilt wird.
Die Grenzen nennt das Projekt selbst ausdrücklich im Abschnitt What it doesn't provide:
- Vertrauen in den Server bleibt nötig. Die Verschlüsselung läuft in JavaScript, das der Server ausliefert. Wer den Server kompromittiert, kann manipuliertes JavaScript ausliefern, das Klartext oder Schlüssel künftig abgreift. Bereits gespeicherte Dokumente bleiben bei einem Einbruch zwar verschlüsselt, neue Eingaben sind aber nicht mehr geschützt.
- Der Link ist der Schlüssel. Wer den vollständigen Link hat, kann ein Dokument ohne Passwort lesen. Links in Tickets oder Chats sind damit genauso sensibel wie das Geheimnis selbst.
- Metadaten sind nicht verschlüsselt. Erstellungszeit, Ablaufzeit, Format, Diskussions- und Burn-Flag sowie das IP-basierte Kommentar-Icon liegen im Klartext vor. Zugriffe stehen außerdem in den Webserver-Logs.
- HTTPS ist Pflicht. Ohne TLS kann jeder auf dem Transportweg das JavaScript verändern, und Chromium-basierte Browser stellen die Web Crypto API über unverschlüsseltes HTTP gar nicht bereit.
PrivateBin ist damit ein Werkzeug für die kurzlebige Übergabe, kein Passwortmanager. Für die dauerhafte Ablage von Zugangsdaten im Team gehören Geheimnisse in einen Tresor wie Vaultwarden oder Passbolt. Lizenz: PrivateBin selbst steht unter der Zlib/libpng-Lizenz, enthaltene Bibliotheken unter GPLv2, BSD, MIT, Apache und CC-BY, aufgeführt in LICENSE.md.
Voraussetzungen und Ressourcen
- Linux-Host mit Docker Engine und Docker Compose v2.
- Eine eigene Subdomain, zum Beispiel
paste.example.de, mit DNS-Eintrag auf den Server. - Ein Reverse Proxy mit TLS-Zertifikat, zum Beispiel Caddy, Traefik oder Nginx.
- Wenig Ressourcen: Im Test belegte der Container direkt nach dem Start rund 28 MiB RAM, das Image ist etwa 40 MB groß.
Das Image enthält Nginx und PHP-FPM, gestartet über s6. Nginx lauscht im Container auf Port 8080 und spricht nur HTTP, TLS übernimmt der vorgeschaltete Proxy. Als Speicher dient standardmäßig das Dateisystem unter /srv/data, eine Datenbank ist nicht nötig.
Plattformen, Architekturen und getestete Version
Das Manifest von privatebin/nginx-fpm-alpine:2.0.6 enthält Images für linux/amd64, linux/386, linux/arm/v6, linux/arm/v7, linux/arm64, linux/ppc64le und linux/s390x. Damit laufen auch Raspberry Pi und ARM-Server. Basis ist Alpine 3.24 mit PHP 8.5, der Build prüft laut Dockerfile die GPG-Signatur des PrivateBin-Release-Archivs. Neben dem All-in-One-Image gibt es schlankere Varianten für einzelne Backends: privatebin/fs, privatebin/pdo, privatebin/gcs und privatebin/s3.
| Tag | Bedeutung laut Image-Doku | Empfehlung |
|---|---|---|
2.0.6 | PrivateBin 2.0.6, wird bei wichtigen Alpine-Sicherheitsfixes neu gebaut | Produktion mit kontrollierten Updates |
2.0.6-alpine3.24 | Unveränderliches Image für exakte Reproduzierbarkeit | Wenn jede Änderung abgenommen werden muss |
stable | Neuestes Release auf dem letzten getaggten Image-Stand | Automatische Updates |
latest / nightly | Neuestes Release auf aktualisiertem Alpine, häufige Rebuilds | Nur mit Monitoring |
edge | Vorschau auf kommendes Alpine | Nicht für Produktion |
Getestet wurde Version 2.0.6 (Label org.opencontainers.image.version=2.0.6) auf amd64 mit Docker 29.1.3 und Compose 2.40.3.
Vollständige compose.yaml und .env
Die Datei setzt die Empfehlungen aus der offiziellen Image-Dokumentation in Compose um: schreibgeschütztes Root-Dateisystem, tmpfs für die Laufzeitverzeichnisse, persistentes Volume für /srv/data und die eigene conf.php schreibgeschützt eingebunden. Zusätzlich werden alle Linux-Capabilities entzogen und ein Speicherlimit gesetzt.
name: privatebin
services:
privatebin:
image: privatebin/nginx-fpm-alpine:${PRIVATEBIN_TAG:-2.0.6}
container_name: privatebin
restart: unless-stopped
# Root-Dateisystem schreibgeschützt, beschreibbar nur Volumes und tmpfs
read_only: true
user: "65534:82"
ports:
- "${PRIVATEBIN_BIND:-127.0.0.1:8080}:8080"
environment:
TZ: ${TZ:-Europe/Berlin}
PHP_TZ: ${TZ:-Europe/Berlin}
volumes:
- privatebin-data:/srv/data
- ./conf.php:/srv/cfg/conf.php:ro
tmpfs:
- /tmp:nodev,noexec,mode=1777
- /run:nodev,exec,mode=1777
- /var/lib/nginx/tmp:nodev,noexec,mode=1777
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
mem_limit: 128m
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8080/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
privatebin-data:
# /opt/privatebin/.env
# Image-Version fest pinnen, Updates bewusst per Tag-Wechsel
PRIVATEBIN_TAG=2.0.6
# Nur lokal binden, der Reverse Proxy spricht mit diesem Port
PRIVATEBIN_BIND=127.0.0.1:8080
TZ=Europe/Berlin
| Parameter | Wirkung |
|---|---|
read_only: true | Root-Dateisystem schreibgeschützt. Beschreibbar sind nur /srv/data und die tmpfs-Pfade, ein Angreifer kann keine Programmdateien überschreiben. |
user: "65534:82" | Entspricht dem User im Image (nobody, Gruppe www-data). Explizit gesetzt, damit ein geändertes Image nicht still als root läuft. |
tmpfs | /run braucht exec für den Prozessmanager s6, /tmp und der Nginx-Puffer kommen ohne aus. |
cap_drop: ALL | Der Dienst bindet Port 8080 und braucht keine Sonderrechte. |
PHP_TZ | Zeitzone für PHP. Laut Doku später nicht mehr ändern, sonst laufen bestehende Dokumente früher oder später ab. |
./conf.php:/srv/cfg/conf.php:ro | Eigene Konfiguration. Ohne diese Zeile nutzt PrivateBin Standardwerte. |
healthcheck | Nutzt das im Image vorhandene BusyBox-wget, der Status erscheint in docker compose ps. |
conf.php: die wichtigsten Einstellungen
Die Konfiguration ist eine INI-Datei mit PHP-Endung, die erste Zeile verhindert die Auslieferung als Webseite. Basis ist immer die conf.sample.php aus dem Release-Tag, dort sind alle Optionen kommentiert. Der folgende Auszug zeigt die für ein Firmen-Setup geänderten und relevanten Werte, der Rest bleibt wie im Beispiel.
[main]
name = "PrivateBin intern"
basepath = "https://paste.example.de/"
discussion = true
opendiscussion = false
password = true
fileupload = false
burnafterreadingselected = true
defaultformatter = "plaintext"
sizelimit = 10000000
qrcode = true
[expire]
default = "1day"
[traffic]
limit = 10
header = "X_FORWARDED_FOR"
[purge]
limit = 300
batchsize = 10
[model]
class = Filesystem
[model_options]
dir = PATH "data"
| Option | Wirkung |
|---|---|
basepath | Öffentliche URL mit abschließendem Schrägstrich. Nötig für korrekte Vorschaulinks. |
burnafterreadingselected | Setzt Löschen nach dem ersten Lesen als Vorauswahl. Für Zugangsdaten sinnvoll. |
[expire] default | Vorausgewählte Ablaufzeit. Wählbar sind 5 Minuten bis 1 Jahr oder never, definiert in [expire_options]. Wer never nicht anbieten will, entfernt die Zeile dort. |
fileupload | Dateianhänge, standardmäßig aus. Grenze ist sizelimit (10 MB) und im Image-Nginx client_max_body_size 15M. |
discussion / opendiscussion | Diskussionen erlauben bzw. vorauswählen. |
[traffic] limit | Mindestabstand in Sekunden zwischen zwei Einträgen derselben IP. |
[traffic] header | Header mit der echten Client-IP hinter dem Reverse Proxy. Ohne ihn gilt das Limit für die Proxy-IP und damit für alle Nutzer gemeinsam. |
creators | Optional: nur bestimmte IPs oder Netze dürfen Dokumente anlegen, etwa das Firmennetz oder VPN. |
[purge] | Wie oft und wie viele abgelaufene Dokumente beim Anlegen neuer Einträge entfernt werden. |
Installation und Start
# Projektverzeichnis anlegen
sudo mkdir -p /opt/privatebin
cd /opt/privatebin
# Beispielkonfiguration aus dem Release-Tag laden
sudo curl -fsSL -o conf.php https://raw.githubusercontent.com/PrivateBin/PrivateBin/2.0.6/cfg/conf.sample.php
# Container läuft als UID 65534, die Datei muss für ihn lesbar sein
sudo chmod 644 conf.php
# compose.yaml und .env wie oben anlegen, dann starten
sudo docker compose up -d
sudo docker compose ps
Nach wenigen Sekunden meldet docker compose ps den Status healthy. Im Log erscheinen fpm is running und ready to handle connections. Beim ersten Speichern legt PrivateBin in /srv/data die Datei salt.php an, einen zufälligen Server-Salt für Löschtokens, Traffic-Limiter und Kommentar-Icons.
Funktionsprüfung und Healthcheck
# HTTP-Status der Startseite
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/
# Sicherheitsheader ansehen
curl -sI http://127.0.0.1:8080/ | grep -i "content-security-policy\|x-frame-options\|referrer-policy"
# Prozess-User und Rechte im Datenpfad
docker exec privatebin sh -c 'id; ls -la /srv/data'
# Statistik über gespeicherte Dokumente
docker exec -t privatebin administration --statistics
Im Test lieferte die Startseite HTTP 200 mit einer strengen Content-Security-Policy (default-src 'none', sandbox), X-Frame-Options: deny und Referrer-Policy: no-referrer. Der PHP-Prozess lief als uid=65534(nobody) gid=82(www-data), Schreibversuche in /var/www oder /etc scheiterten mit Read-only file system.
Dass der Server nichts Lesbares speichert, lässt sich mit der JSON-API zeigen. Dokumente wurden im Test mit einem kleinen Skript nach der offiziellen Spezifikation des Verschlüsselungsformats angelegt. Die Serverantwort zum Abruf enthält nur Parameter und Chiffretext:
# Abruf eines Dokuments über die JSON-API (liefert nur Chiffretext)
curl -s -H "X-Requested-With: JSONHttpRequest" "http://127.0.0.1:8080/?dae1fd2ec834b764"
# Antwort (gekürzt)
{"status":0,"id":"dae1fd2ec834b764","adata":[["BusBQkxRL5GtRw64NnDsVQ==","WbGiM6axdtQ=",100000,256,128,"aes","gcm","zlib"],"plaintext",0,0],"meta":{"time_to_live":86395},"v":2,"ct":"oI7lE0rjS4bZhvrK5ISyqNHKZjWtI614..."}
Mit dem richtigen Schlüssel aus dem Link ließ sich der Text entschlüsseln, mit einem falschen Schlüssel oder ohne das gesetzte Passwort schlug die GCM-Authentifizierung fehl. Wer die API skripten will, findet im Projekt-Wiki mehrere Kommandozeilen-Clients, etwa PBinCLI in Python.
Ablaufzeit, Burn after reading und Diskussionen
Jedes Dokument bekommt eine Ablaufzeit. Abgelaufene Einträge liefert PrivateBin nicht mehr aus und löscht sie beim nächsten Purge-Lauf. Mit Burn after reading wird das Dokument nach dem ersten Abruf entfernt. Im Test lieferte der erste Abruf den Inhalt, der zweite Document does not exist, has expired or has been deleted.
Ein praktisches Problem sind Link-Scanner in E-Mail- und Chat-Sicherheitslösungen: Führen sie JavaScript aus, öffnen sie das Dokument, bevor der Empfänger es sieht, und es ist verbrannt. Seit den Versionen nach 1.7 unterstützt PrivateBin deshalb Links mit einem Bindestrich nach dem #, also ?id#-schlüssel. Solche Links fragen vor dem Laden nach einer Bestätigung. Bei Burn-Dokumenten zeigt die Oberfläche zudem den Hinweis This secret message can only be displayed once.
Beim Anlegen erhält der Ersteller zusätzlich einen Löschtoken. Mit ihm lässt sich ein Dokument vorzeitig entfernen, ein falscher Token wird mit Wrong deletion token. Document was not deleted. abgelehnt. Diskussionen erlauben verschlüsselte Kommentare unter einem Dokument. Für Zugangsdaten sind sie selten nötig. Wer sie deaktiviert, entfernt auch die IP-basierten Kommentar-Icons, die das Projekt selbst als schwachen Mechanismus beschreibt.
Persistente Daten und Rechte
Alles, was bleiben muss, liegt in /srv/data: Dokumente in zweistufigen Unterverzeichnissen nach den ersten Zeichen der ID, dazu salt.php, traffic_limiter.php und purge_limiter.php. Im Test waren die Verzeichnisse mit drwx------ und die Dateien mit -rw-r----- angelegt, Eigentümer nobody:www-data, also 65534:82.
Die Image-Dokumentation schreibt vor, dass das eingehängte Verzeichnis 65534:82 gehören muss. Bei einem Named Volume erledigt Docker das automatisch, weil es die Rechte aus dem Image übernimmt. Bei einem Bind-Mount wie ./data:/srv/data muss der Admin selbst nachhelfen. Wer Docker mit userns-remap betreibt, addiert den subuid- und subgid-Bereich zu diesen Werten.
# Eigentümer eines Bind-Mounts auf den Container-User setzen
sudo chown -R 65534:82 /opt/privatebin/data
# Log nach der eigentlichen Ursache durchsuchen
docker compose logs --no-log-prefix | grep -i "permission denied\|failed to store"
Für die Pflege abgelaufener Dokumente bringt das Image ein Verwaltungsskript mit:
# Abgelaufene Dokumente sofort entfernen, etwa nächtlich per Cron
docker exec privatebin administration --purge
# Leere Verzeichnisse des Filesystem-Backends aufräumen
docker exec privatebin administration --empty-dirs
# Einzelnes Dokument serverseitig löschen
docker exec privatebin administration --delete dae1fd2ec834b764
Netzwerkfreigabe, Reverse Proxy und TLS
Der Container bindet in der compose.yaml nur an 127.0.0.1:8080 und ist so von außen nicht erreichbar. Nach außen spricht ausschließlich der Reverse Proxy mit gültigem Zertifikat. Das ist hier keine Stilfrage: Das Projekt schreibt HTTPS vor und empfiehlt zusätzlich HSTS. Über HTTP zeigt PrivateBin die Warnung This website is using an insecure connection! Please only use it for testing., und Chromium-basierte Browser deaktivieren laut Projekt-FAQ die Web Crypto API außerhalb eines sicheren Kontexts, ohne die weder Ver- noch Entschlüsselung funktioniert. Den Schalter httpwarning sollten Sie nicht abschalten.
Ein Minimalbeispiel mit Caddy, das Zertifikate automatisch bezieht:
# /etc/caddy/Caddyfile
paste.example.de {
encode gzip
header Strict-Transport-Security "max-age=31536000"
reverse_proxy 127.0.0.1:8080
}
Caddy setzt X-Forwarded-For selbst, passend zu header = "X_FORWARDED_FOR" in der conf.php. Bei Nginx gehört proxy_set_header X-Forwarded-For $remote_addr; in den Location-Block. So steht dort nur die tatsächliche Client-Adresse und kein vom Client mitgeschickter Wert. Läuft ein CDN oder DDoS-Schutz davor, der eigene Skripte in Seiten einfügt, bricht die Content-Security-Policy. Die FAQ behandelt diesen Fall gesondert. Wer die Instanz nur intern anbieten will, beschränkt mit creators das Anlegen auf Firmen- und VPN-Netze, das Lesen bleibt dann weiter für Empfänger mit Link möglich. Nach der Einrichtung empfiehlt das Projekt, die Instanz mit SSL Labs, securityheaders und dem Mozilla Observatory zu prüfen.
Backup und Restore
Gesichert wird das Volume /srv/data vollständig, einschließlich salt.php. Ohne den Salt funktionieren Löschtokens bestehender Dokumente nicht mehr. Die Schlüssel zu den Dokumenten liegen dagegen nie auf dem Server, ein Backup enthält also nur Chiffretext und ist ohne die verteilten Links wertlos. Für den Betrieb heißt das: Das Backup schützt vor Datenverlust, verschafft dem Admin aber keinen Zugriff auf Inhalte.
cd /opt/privatebin
# Kurz anhalten, damit kein Schreibvorgang mitten im Archiv landet
docker compose stop
# Volume schreibgeschützt einhängen und als tar.gz auf den Host streamen
docker run --rm -v privatebin_privatebin-data:/srv/data:ro --entrypoint tar privatebin/nginx-fpm-alpine:2.0.6 -C /srv/data -czf - . > privatebin-data-$(date +%F).tar.gz
docker compose start
# Inhalt prüfen
tar -tzf privatebin-data-$(date +%F).tar.gz | head
Der Restore spielt das Archiv in ein frisches Volume zurück. Weil docker compose create das Volume aus dem Image mit Eigentümer 65534:82 anlegt, läuft das Entpacken als derselbe User und die Rechte stimmen ohne weitere Nacharbeit.
cd /opt/privatebin
# ACHTUNG: löscht das aktuelle Volume mit allen Dokumenten
docker compose down -v
# Container und leeres Volume anlegen, aber noch nicht starten
docker compose create
# Archiv als Container-User 65534:82 zurückspielen
docker run --rm -i --user 65534:82 -v privatebin_privatebin-data:/srv/data --entrypoint tar privatebin/nginx-fpm-alpine:2.0.6 -C /srv/data -xzf - < privatebin-data-2026-09-26.tar.gz
docker compose start
Im Test wurde genau dieser Ablauf durchgespielt: Backup erstellt, Volume mit down -v gelöscht, Restore eingespielt. Die Prüfsumme von salt.php war vorher und nachher identisch, und ein vor dem Backup angelegtes Dokument ließ sich mit seinem ursprünglichen Link-Schlüssel wieder entschlüsseln. Da viele Dokumente ohnehin nach Stunden ablaufen, reicht meist eine tägliche Sicherung mit kurzer Aufbewahrung. Längere Aufbewahrung konserviert Chiffretexte, die eigentlich längst gelöscht sein sollten.
Updates und Rollback-Grenzen
Updates erfolgen über einen neuen Image-Tag. Vorher immer das Volume sichern und die conf.sample.php des neuen Releases mit der eigenen conf.php vergleichen, weil neue Optionen sonst auf Standardwerten bleiben.
cd /opt/privatebin
# Vorher sichern (siehe Backup), dann Tag in .env anheben
# 2.0.7 ist nur ein Platzhalter für den nächsten Release-Tag
sed -i 's/^PRIVATEBIN_TAG=.*/PRIVATEBIN_TAG=2.0.7/' .env
docker compose pull
docker compose up -d
docker compose ps
# Rollback: alten Tag eintragen und erneut hochfahren
sed -i 's/^PRIVATEBIN_TAG=.*/PRIVATEBIN_TAG=2.0.6/' .env
docker compose up -d
Im Test lief ein Wechsel von 2.0.6 auf 2.0.5 und zurück mit denselben Daten problemlos, ein Passwort-Dokument blieb in beiden Richtungen lesbar. Das gilt innerhalb derselben Hauptversion mit unverändertem Speicherformat. Ein Downgrade über größere Versionssprünge beschreibt das Projekt nicht als unterstützten Weg. Sicher ist dort nur der Restore des Backups von vor dem Update, deshalb vor jedem Hauptversionswechsel die Versionshinweise im Repository lesen.
Typische Fehler mit Diagnose und Lösung
| Symptom | Ursache | Lösung |
|---|---|---|
Startseite lädt, Speichern meldet Error saving document. Sorry., im Log mkdir(): Permission denied und failed to store the server salt | Datenverzeichnis gehört nicht 65534:82, typisch bei Bind-Mounts. Healthcheck bleibt trotzdem grün. | chown -R 65534:82 auf das Verzeichnis, danach Neustart |
Eigene Einstellungen wirken nicht, Seite heißt wieder PrivateBin | conf.php für UID 65534 nicht lesbar (etwa chmod 600). PrivateBin fällt dann ohne Fehlermeldung auf Standardwerte zurück. | chmod 644 conf.php, Container neu starten |
Please wait 10 seconds between each post. | Traffic-Limiter. Hinter einem Proxy ohne IP-Header teilen sich alle Nutzer ein Limit. | header = "X_FORWARDED_FOR" setzen, bei Bedarf exempted für Netze |
Document does not exist, has expired or has been deleted. | Dokument abgelaufen, per Burn after reading bereits gelesen oder gelöscht | Neu anlegen lassen. Bei Mail-Links die Variante mit #- nutzen |
| Warnung insecure connection oder Meldung PrivateBin requires a modern browser to work | Zugriff über HTTP, Web Crypto API oder WebAssembly nicht verfügbar | Nur über HTTPS anbieten, Browser aktualisieren |
| Text lässt sich trotz Link nicht entschlüsseln | Link gekürzt (Fragment fehlt), falsches oder fehlendes Passwort | Vollständigen Link inklusive #-Teil übergeben, Passwort prüfen |
administration --statistics zeigt PHP Deprecated-Zeilen | Hinweis von PHP 8.5 im Skript, im Test ohne Einfluss auf das Ergebnis | Ignorieren, die Zählwerte stimmen |
Saubere Deinstallation
Warnung: Die folgenden Befehle löschen alle gespeicherten Dokumente endgültig. Ohne vorheriges Backup gibt es keinen Weg zurück, und alle bereits verteilten Links werden ungültig. Prüfen Sie vorher, ob noch jemand auf ein Dokument angewiesen ist.
cd /opt/privatebin
# Container, Netzwerk UND Volume mit allen Dokumenten entfernen
docker compose down -v --remove-orphans
# Image namentlich entfernen
docker rmi privatebin/nginx-fpm-alpine:2.0.6
# Projektverzeichnis mit conf.php und Backups löschen
cd / && sudo rm -rf /opt/privatebin
Danach sollten docker ps -a --filter name=privatebin und docker volume ls --filter name=privatebin leer sein. Den Eintrag im Reverse Proxy und den DNS-Eintrag nicht vergessen.
Testumfang
Getestet am 26.09.2026 mit dem Image 2.0.6 auf amd64 in einer isolierten Umgebung (Port 127.0.0.1:18471): Start mit schreibgeschütztem Root-Dateisystem, HTTP 200 und Sicherheitsheader, Anlegen und Abrufen verschlüsselter Dokumente über die JSON-API inklusive Passwort, Burn after reading, Löschtoken und Traffic-Limiter, Rechte in /srv/data, Backup mit Löschung und Restore, Wechsel auf 2.0.5 und zurück sowie die Fehlerbilder falscher Volume-Rechte und unlesbarer conf.php. Nur aus der Dokumentation übernommen sind die Browser-Oberfläche, das WebCrypto-Verhalten der Browser, Reverse Proxy mit TLS, Diskussionen, Dateiuploads, Datenbank- und Cloud-Backends sowie andere Architekturen als amd64.
Passende Anleitungen auf S-EDV
- Caddy als Reverse Proxy mit automatischem HTTPS: der passende Unterbau für die TLS-Pflicht von PrivateBin.
- Docker Compose absichern: Secrets, Healthchecks, Non-Root: die Härtungsoptionen aus dieser compose.yaml im Detail.
- Vaultwarden härten, sichern und mit Fail2ban schützen: für Zugangsdaten, die dauerhaft im Team bleiben sollen.
Quellen
- PrivateBin: Projekt-Repository und README (What it doesn't provide)
- PrivateBin: offizielles Docker-Image, Dockerfile und Dokumentation
- Docker Hub: privatebin/nginx-fpm-alpine, Tags und Architekturen
- PrivateBin: conf.sample.php mit allen Optionen
- PrivateBin Wiki: FAQ zu HTTPS, Web Crypto API und Metadaten
- PrivateBin Wiki: Verschlüsselungsformat und URL-Aufbau
- PrivateBin Wiki: JSON-API
- PrivateBin: Release 2.0.6