Paperless-ngx Backup & Restore: Die richtige Strategie
So erstellst du ein sicheres, inkrementelles Backup deiner Paperless-ngx Instanz mit Docker und stellst es im Notfall wieder her.
Inhaltsverzeichnis
Ein Dokumentenmanagementsystem (DMS) wie Paperless-ngx ist das Herzstück des papierlosen Büros. Aber was passiert, wenn der Server ausfällt, ein Update fehlschlägt oder die Datenbank korrupt ist? Ohne ein vernünftiges Backup sind nicht nur die Einstellungen weg, sondern im schlimmsten Fall deine wichtigen Dokumente.
Ich dir eine robuste Backup-Strategie zeigen, die sowohl die einzelne Datenbank als auch die Dateien sichert – und das Ganze platzsparend und automatisiert.
Warum einfach Ordner kopieren nicht reicht
Viele Nutzer kopieren einfach den gesamten Docker-Ordner. Das kann funktionieren, birgt aber Risiken:
- Datenbank-Konsistenz: Wenn du die Datenbank-Dateien (PostgreSQL) kopierst, während der Container läuft, kann das Backup korrupt und unbrauchbar sein.
- Interne Verknüpfungen: Paperless verknüpft Dokumente in der Datenbank mit Dateien im Dateisystem. Wenn diese nicht synchron gesichert werden, gibt es Probleme.
Die sauberste Lösung ist eine Kombination aus einem SQL-Dump der Datenbank und dem integrierten Document Exporter von Paperless.
Die Strategie
Wir wollen folgendes erreichen:
- Einen sauberen Dump der PostgreSQL-Datenbank erstellen.
- Die Dokumente mit dem Paperless Exporter in ein verarbeitbares Format bringen (dabei werden auch Metadaten in
json-Dateien geschrieben). - Diese Daten inkrementell sichern, um Speicherplatz zu sparen (wir wollen nicht jeden Tag 10 GB kopieren, wenn sich nur zwei PDFs geändert haben).
- Alte Backups automatisch löschen (Retention Policy).
Vorbereitung
Erstelle auf deinem Server eine Datei, z.B. backup-paperless.sh.
nano /home/deployn/paperless/backup-paperless.sh
Füge folgenden Inhalt ein und passe die Variablen oben an deine Pfade an:
#!/bin/bash
set -e
set -o pipefail
# --- KONFIGURATION ---
# Pfad, wo die Backups landen sollen
BACKUP_BASE_DIR="/home/deployn/backup"
# Dein Paperless-Verzeichnis (wo die compose.yaml liegt)
PAPERLESS_DIR="/home/deployn/paperless"
# Name des Symlinks für das letzte Backup
LATEST_LINK="${BACKUP_BASE_DIR}/latest"
# Namen der Container (prüfe das mit 'docker container ls')
PG_CONTAINER="paperless-db"
WEBSERVER_CONTAINER="paperless-webserver"
# Datenbank Zugangsdaten (aus deiner docker-compose.yml)
PG_USER="paperless"
PG_DB="paperless"
# Wie viele Tage sollen Backups behalten werden?
RETENTION_DAYS=30
DOCKER_CMD="/usr/bin/docker"
DOCKER_COMPOSE_CMD="/usr/bin/docker compose"
echo "========================================================"
echo "Starte Paperless-Backup: $(date)"
echo "========================================================"
# 1. Neues Backup-Verzeichnis erstellen
DATE_STAMP=$(date +"%Y-%m-%d_%H-%M-%S")
BACKUP_DIR="${BACKUP_BASE_DIR}/${DATE_STAMP}"
mkdir -p "${BACKUP_DIR}"
echo "[+] Erstelle Backup-Verzeichnis: ${BACKUP_DIR}"
# 2. PostgreSQL-Datenbank sichern
echo "[+] Erstelle PostgreSQL-Dump..."
${DOCKER_CMD} exec "${PG_CONTAINER}" pg_dump -U "${PG_USER}" -d "${PG_DB}" > "${BACKUP_DIR}/paperless-db.sql"
# Prüfen ob der Dump leer ist
if [ ! -s "${BACKUP_DIR}/paperless-db.sql" ]; then
echo "FEHLER: Datenbank-Dump ist leer!"
rm -rf "${BACKUP_DIR}"
exit 1
fi
echo " -> Datenbank-Dump erfolgreich."
# 3. Paperless Dokumente exportieren
echo "[+] Starte den document_exporter..."
cd "${PAPERLESS_DIR}"
${DOCKER_COMPOSE_CMD} exec -T "${WEBSERVER_CONTAINER}" document_exporter ../export
echo " -> Document-Exporter erfolgreich ausgeführt."
# 4. Dokumente inkrementell mit rsync und Hard-Links sichern
echo "[+] Synchronisiere Dokumente..."
if [ -d "${LATEST_LINK}" ]; then
LINK_DEST_OPTION="--link-dest=${LATEST_LINK}/documents"
echo " -> Vorheriges Backup gefunden. Nutze Hard-Links."
else
LINK_DEST_OPTION=""
echo " -> Kein vorheriges Backup gefunden. Erstelle Voll-Kopie."
fi
# Annahme: ./export ist im PAPERLESS_DIR gemountet
rsync -a --delete ${LINK_DEST_OPTION} "${PAPERLESS_DIR}/export/" "${BACKUP_DIR}/documents/"
echo " -> Dokumente synchronisiert."
# 5. 'latest' Symlink aktualisieren
echo "[+] Aktualisiere 'latest'-Link."
ln -snf "${BACKUP_DIR}" "${LATEST_LINK}"
# 6. Alte Backups löschen
echo "[+] Lösche Backups älter als ${RETENTION_DAYS} Tage..."
find "${BACKUP_BASE_DIR}" -maxdepth 1 -type d -not -name "latest" -mtime +${RETENTION_DAYS} -exec rm -rf {} \;
echo " -> Bereinigung abgeschlossen."
echo "========================================================"
echo "Paperless-Backup erfolgreich abgeschlossen!"
echo "========================================================"
Skript ausführbar machen
Damit das Skript läuft, müssen wir ihm die entsprechenden Rechte geben:
chmod +x /home/deployn/paperless/backup-paperless.sh
Wichtig: Der Export-Pfad
Das Skript geht davon aus, dass du in deiner compose.yaml ein Volume für den Export definiert hast. Das sollte ungefähr so aussehen:
volumes:
- ./data:/usr/src/paperless/data
- ./media:/usr/src/paperless/media
- ./export:/usr/src/paperless/export # <--- WICHTIG
- ./consume:/usr/src/paperless/consume
Der document_exporter Befehl im Skript (../export) bezieht sich auf den Pfad innerhalb des Containers. Da Paperless im Container oft in /usr/src/paperless/src arbeitet, führt ../export zu /usr/src/paperless/export, was wir nach außen gemappt haben.
Automatisierung mit Cron
Niemand macht Backups gerne manuell. Richten wir einen Cronjob ein, der das jede Nacht um 3 Uhr erledigt.
crontab -e
Füge folgende Zeile hinzu (angepasst an deinen Pfad):
0 3 * * * /home/deployn/paperless/backup-paperless.sh >> /var/log/paperless_backup.log 2>&1
Oder erstelle einen anderen Zeitplan.
Restore: Der Ernstfall (Disaster Recovery)
Ein Backup ist wertlos, wenn man es nicht wiederherstellen kann. Hier ist der Weg zurück, falls dein Server komplett neu aufgesetzt werden muss.
0. Vorbereitung
Initialisiere ein neues Paperless Verzeichnis frisch mit Docker Compose, als wäre es ein neuer Server.
1. Datenbank wiederherstellen
Kopiere die paperless-db.sql aus deinem Backup auf den Server, zum Beispiel in das ./tmp Verzeichnis im Paperless Ordner.
Mounte das Backup in den Datenbank-Container:
paperless-db:
volumes:
- ./tmp:/tmp
2. Saubere Installation
Starte nur den Datenbank-Container, damit die Datenbank bereit ist.
docker compose up -d paperless-db
3. Dokumente importieren
Das ist der wichtigste Schritt. Wir kopieren die Dokumente aus dem Backup in den export-Ordner der neuen Installation und lassen Paperless diese importieren.
- Kopiere den Inhalt von
backup/documents/in denexport-Ordner deiner neuen Installation. - Starte den Paperless Webserver-Container.
- Führe den Importer aus:
docker compose exec webserver document_importer ../export
Der Importer liest die manifest.json Dateien, importiert die Dokumente zurück in das System, stellt die Verknüpfungen in der Datenbank her und baut den Suchindex neu auf.
3-2-1 Regel nicht vergessen
Das Skript oben sichert die Daten lokal in einen anderen Ordner. Wenn deine Festplatte stirbt, ist auch das Backup weg.
Du solltest den Ordner ${BACKUP_BASE_DIR} unbedingt auf ein externes Ziel kopieren. Das kannst du beispielsweise mit:
- Rclone (Upload zu Google Drive, OneDrive, S3)
- BorgBackup (Verschlüsseltes Backup auf einen anderen Server)
- Synology Hyper Backup (Wenn du auf einem NAS bist)
Fazit
Mit diesem Skript hast du eine “Set and Forget”-Lösung, die dank Hard-Links extrem effizient mit deinem Speicherplatz umgeht, aber trotzdem für jeden Tag ein vollständiges Abbild deiner Dokumente und Datenbank vorhält.
Teste den Restore-Prozess unbedingt einmal in einer virtuellen Maschine oder auf einem Test-System, bevor du dich im Notfall darauf verlassen musst!