Paperless ngx - Synology - Backup/Restore ist nicht trivial oder geht es auch anders?

Intro

In meinen Augen ist Paperless Backup/Restore alles andere als trivial für Anfänger ohne Dockererfahrung aber wer will schon seine eingescannten Dokumente etc verlieren.
Wie heißt es immer so schön, kein Backup → kein Mitleid

Solltet Ihr wie ich

  • am Anfang von Dockern und Paperless stehen
  • Paperless auf der Synology NAS im Container Manager als Docker Projekt installiert haben
  • den Notfall oder Datenbank Update durchspielen
  • ein Backup/Restore einrichten wollt

Dann helfen Euch diese Notizen ein paar Stunden Irrweg zu sparen.

Anleitungen im Internet funktionieren nur manchmal und es hängt davon ab, wie Paperless installiert wurde.

An alle Profis und Leute mit mehr Erfahrungen: Wie richtet man besten eine automatisiertes Backup von Paperless Datenbank an? Eure Vorschläge sind sehr willkommen. Danke!

Meine Testinstallation heißt:

  • “paperless-office”
  • und liegt im NAS Pfad “/volume1/docker/paperless-office”

Das ist wichtig, da untere Befehle auf Eure Installation angepaßt werden müssen.

1. Backup & Restore by Hyperbackup

Vorteil:

  • Man kann immer auf genau den Stand zurückgreifen inklusive Daten und Container Version.

Beides

  • Eventuelle Container Update Spielerein/Tests sind weg.

Restore Nachteile bzw. zu bedenken

  • Hyperbackup löscht / überschreibt nicht das Docker Zielverzeichnis!
  • Hyperbackup überschreibt nicht das Docker Projekt im Container Manager!

Backup Vorgehensweise erkäre ich hier nicht. Das geht intuitiv.

Restore Vorgehensweise:

a) Container Manager Projekt stoppen
b) Docker\paperless-office alles inklusive der compose.yaml manuell löschen
c) Sofern einer der Container manuell angefaßt wurde (z.B. Update), müssen Container/Images händisch gelöscht werden
d) Hyperbackup Restore durchführen
e) Container Manager
e1) Sofern Projekt noch vorhanden, dann Projekt neu starten
e2) Falls Projekt gelöscht, Projekt neu anlegen mit der wieder hergestellten compose.yaml

2. Backup per SSH

Vorteile:

  • Wer auf manuelle Kommandozeilen Befehle steht und sich auskennt, wird es mögen
  • Man bekommt direkt Rückmeldung mit ggf. Fehlern

Nachteile:

  • Umständlich entweder nach Erinnerung manuell oder automatisiert über Aufgabenmanager

Anlegen eines Datenbank Dumps

a) Ggf. Hyperbackup Backup vorher durchführen falls was schief läuft
b) per ssh admin@192.168.x.xxx anmelden
c) find /volume1/docker -name “*.sql” → findet bereits vorhandene Dumps
d) cd /volume1/docker/paperless-office → wechselt in den Container
e) sudo docker exec paperless-office-postgres bash -c “pg_dump -U paperless > /var/lib/postgresql/data/backup_$(date +%F).sql” → erstellt den Dump
f) Sichere den Dump in ein extra Verzeichnis außerhalb von Docker (falls Du von vorne beginnen mußt und alles löschen mußt und nicht aus Versehen auch den Dump löschst)

Export der Dokumente

a) per ssh admin@192.168.x.xxx anmelden
b) cd /volume1/docker/paperless-office → wechselt in den Container
c) falls nicht vorhanden export Verzeichnis anlegen
d) sudo docker-compose exec webserver document_exporter …/export/

3. Restore per SSH

Vorteile:

  • Datenbank und Export können auch bei komplett neuen/aktualisierten Containern eingespielt werden
  • Man bekommt direkt Rückmeldung mit ggf. Fehlern

Nachteile:

  • Import des Datenbank Dumps geht nur bei leerer Datenbank!
  • Fehlermeldungen können irritieren

Import des Datenbank Dumps

a) Im Container Manager Projekt stoppen und löschen (nachprüfen ob Images auch weg sind)
b) Im Zielodner neue Paperless Strucktur anlegen bzw. vorhandene Ordner leeren (compose.yaml muß bleiben)
c) export Ordner zurückspielen (aus Hyperbackup oder manueller voriger Kopie)
d) Datenbank Dump in das postgres Verzeichnis kopieren
e) Im Container Manager Projekt neu erstellen basierend auf compose.yaml
f) per ssh admin@192.168.x.xxx anmelden
g) sudo docker exec -i paperless-office-postgres psql -U paperless < /volume1/docker/paperless-office/postgres/backup_2025-03-29.sql → Import des Dumps (achte auf den richtigen Backup Namen im Postgres Verzeichnis)

  • es gibt viele Melungen und Fehler wie
    ERROR: relation “account_emailaddress” already exists ALTER TABLE
    ERROR: relation “documents_comment_id_seq” already exists
    ERROR: relation “documents_correspondent” already exists
    ERROR: multiple primary keys for table “documents_workflowaction_remove_change_groups” are not allowed
    …Fehler irritieren aber auch logisch

Import der exportierten Dokumente

a) DB Dump, wie oben beschrieben, ist ausgeführt
b) desweiteren sind im Export Ordner die früher exportierten Dokumente
c) per ssh admin@192.168.x.xxx anmelden
d) cd /volume1/docker/paperless-office → wechselt in den Container
e) sudo docker-compose exec webserver document_importer …/export/ → startet den

Checking the manifest
Installed 892 object(s) from 1 fixture(s)
Copy files into paperless…
100%|██████████████████████████████████████████████████████████████████████████████████| 32/32 [00:05<00:00, 5.75it/s]
Updating search index…
100%|██████████████████████████████████████████████████████████████████████████████████| 32/32 [00:02<00:00, 13.61it/s]

Und das wars.
Alles so wie vorher.


EDIT:
Ich bat ChatGPT diesen Post zu prüfen und Verbesserungen vorzuschlagen.

  1. Klarere Struktur & Übersichtlichkeit vornehmen
  2. Fehlende Kontextinfos bei Hyper Backup
  3. Automatisierungspotenzial bleibt etwas vage (das stimmt)
  4. Restore-Teil: Etwas mehr Tiefgang
  5. Viel Text ohne Visualisierung – schwer greifbar

Sch… KI :wink:

“Sind seine Anleitungen korrekt?”

… fand nirgends einen Widerspruch…aber

" Automatisierte Backups: Für die Automatisierung von Backups auf einer Synology NAS kann der Aufgabenplaner genutzt werden, um Skripte zu festgelegten Zeiten auszuführen. Ein Beispiel für ein solches Skript könnte die regelmäßige Ausführung des document_exporter-Befehls sein, dessen Ergebnisse dann mit rsync oder anderen Backup-Tools gesichert werden. Diese Methode wird auch in der Paperless-ngx Community diskutiert und empfohlen."

Wenn keine neuen/besseren Ideen im Post kommen, werde ich es so machen:

Wöchentlich automatisiert:

  1. Über Aufgabenplanung: DB Dump eine Datei ohne Datum (z.B.Bacardi-dbdump)(*)
  2. Über Aufgabenplanung: Export der Dokumente
  3. Danach Hyperbackup (mit Versionsrotation und Verschlüsselung)

(*) Oben im dump habe ich Dateinamen mit Datum erzeugen aber das werde ich wieder wegnehmen weil sich sonst das HyperBackup unnötig aufblähen würde. Eine Versionierung überlasse ich dem HyperBackup.

Monatlich manuell:

Manuell Sicherung des HyperBackup Backups in die Cloud über CloudSync (mache ich heute schon so mit anderen Sicherungen)

1 „Gefällt mir“

Bash Script für Synology Aufgabenplaner

  • Beim Einrichten einer Aufgabe: Muß unter root laufen
  • Falls noch nicht vorhanden im Aufgabenplaner Einstellungen einen Logordner angeben.
  • Script
    • leert den Export Ordner *
    • exportiert die Dokumente
    • erzeugt einen Datenbank Dump der Postgress DB (überschreibt den vorigen *)

(*) Meine Idee ist die Versionierung von Sicherungen HyperBackup zu überlassen, deshalb reicht hier immer nur eine Sicherungsdatei bzw. ein Export. Export sollte eigentlich auch über Export gehen aber ich lösche vorher lieber (robuster). Theoretisch könnte man die Sicherungsdatei mit einem Datum im Namen versehen und auch den Export zippen mit Datum im Namern und sich so seine Versionierung aufbauen.

#!/bin/bash

# === Konfiguration ===
PROJECT_DIR="/volume1/docker/paperless-office" #Hier der Pfad zu Eurem paperless
DOKUMENTE_EXPORT_DIR="$PROJECT_DIR/export"

DB_CONTAINER="paperless-office-postgres" #Eurer Datenbank Container
DB_VOLUME_PATH="/var/lib/postgresql/data"  # Container-interner Pfad
DB_DUMP_FILENAME="backup_dbdump.sql" #Name der Dump Datei
DB_DUMP_PATH="$DB_VOLUME_PATH/$DB_DUMP_FILENAME"

# === Export-Verzeichnis prüfen und leeren ===
if [ -n "$DOKUMENTE_EXPORT_DIR" ] && [ -d "$DOKUMENTE_EXPORT_DIR" ]; then
  echo "[INFO] Leere Dokumenten-Export-Verzeichnis: $DOKUMENTE_EXPORT_DIR"
  rm -rf "$DOKUMENTE_EXPORT_DIR"/*
else
  echo "[ERROR] Dokumenten-Export-Verzeichnis existiert nicht. Abbruch."
  exit 1
fi

# === In Projektverzeichnis wechseln ===
cd "$PROJECT_DIR" || { echo "[ERROR] Projektverzeichnis nicht gefunden: $PROJECT_DIR"; exit 1; }

# === Dokumente exportieren ===
echo "[INFO] Starte Dokumenten-Export..."
docker-compose exec -T webserver document_exporter ../export

if [ $? -eq 0 ]; then
  echo "[OK] Dokumenten-Export erfolgreich abgeschlossen."
else
  echo "[ERROR] Fehler beim Dokumenten-Export. Abbruch."
  exit 1
fi

# === PostgreSQL Dump erstellen ===
echo "[INFO] Erstelle PostgreSQL-Dump: $DB_DUMP_PATH"
docker exec "$DB_CONTAINER" pg_dump -U paperless -F p -f "$DB_DUMP_PATH"

if [ $? -eq 0 ]; then
  echo "[OK] Datenbank-Dump erfolgreich gespeichert unter: $PROJECT_DIR/postgres/$DB_DUMP_FILENAME"
else
  echo "[ERROR] Fehler beim Datenbank-Dump!"
  exit 1
fi

[INFO] Leere Dokumenten-Export-Verzeichnis: /volume1/docker/paperless-office/export
[INFO] Starte Dokumenten-Export…

0%| | 0/32 [00:00<?, ?it/s]
19%|█▉ | 6/32 [00:00<00:00, 58.07it/s]
41%|████ | 13/32 [00:00<00:00, 62.85it/s]
62%|██████▎ | 20/32 [00:00<00:00, 40.57it/s]
81%|████████▏ | 26/32 [00:00<00:00, 45.91it/s]
100%|██████████| 32/32 [00:00<00:00, 42.75it/s]
100%|██████████| 32/32 [00:00<00:00, 45.05it/s]
[OK] Dokumenten-Export erfolgreich abgeschlossen.
[INFO] Erstelle PostgreSQL-Dump: /var/lib/postgresql/data/backup_dbdump.sql
[OK] Datenbank-Dump erfolgreich gespeichert unter: /volume1/docker/paperless-office/postgres/backup_dbdump.sql

Wie Postgres Datenbank Container updaten ohne Datenverlust?
(Am Beispiel von 16 auf 17)

Als Anfänger probiert man sich mit compose.yaml Codeschnipseln aus dem Internet bis es geht. So auch ich und es stand dort Postgres 15 und so fing ich mit Postgres 15 an.

services:
  db:
    image: postgres:15

Später las ich auf PostgreSQL: Versioning Policy und probierte mich zur nun stabil laufenden 16. Jetzt gehe ich auf 17 und dokumentiere das für mich und für Interessierte für später wenn 2029 der Support für Version 17 ausläuft.

Dies ist der Weg, der für mich funktionierte:

  1. Backup (DBdump + Export wie oben beschrieben und dann nochmal alles mit Hyperbackup oder ein Kopieren woanders hin - zur Sicherheit falls alles schief geht)
  2. Im Container Manager Projekt paperless-office beenden und löschen (keine Container, keine Images sollten über sein)
  3. Per File Station in den Docker Ordner Paperless-Office wechseln und fast alles aus den Unterordnern löschen (außer compose.yaml, dem Inhalt des export Ordners und im postgres Verzeichnis den oben angelegten DBdump)
  4. Anlegen eines Verzeichnisses “postgress-17” (Unterordner von paperless-office)
  5. Öffnen der compose.yaml per Texteditor
  6. Duplizieren des DB Teils und anpassen des zweiten Teils. Schaut wo ich unter 17 bzw. “-17” hinzugefügt habe und anschließend speichern
  db:
    image: postgres:16
    container_name: paperless-office-postgres
    restart: always
    environment:
      POSTGRES_DB: xxx
      POSTGRES_USER: xxx
      POSTGRES_PASSWORD: xxx
    volumes:
      - /volume1/docker/paperless-office/postgres:/var/lib/postgresql/data
    user: "xxx"
    networks:
      - paperless-office-network

  db-17:
    image: postgres:17
    container_name: paperless-office-postgres-17
    restart: always
    environment:
      POSTGRES_DB: xxx
      POSTGRES_USER: xxx
      POSTGRES_PASSWORD: xxx
    volumes:
      - /volume1/docker/paperless-office/postgres-17:/var/lib/postgresql/data
    user: "xxx"
    networks:
      - paperless-office-network
  1. Im Container Manager Projekt neu erstellen mit vorhandener compose.yaml (Technisch wird ein 2. Datenbank Container erstellt mit leeren Daten.)

Wenn hier Exit Code 0 steht, ist bis dahin alles ok.

Jetzt kommt die Datenmigration.

  1. Alle Container beenden außer postgres17
  2. Kopiert die Datei backup_dbdump.sql von postgres zu postgres-17
  3. per SSH anmelden admin@192.168.xxx.xxx
  4. cd /volume1/docker/paperless-office → zu den Containern wechseln
  5. Den Import des DBdumps starten:
sudo docker exec -i paperless-office-postgres-17 psql -U paperless < /volume1/docker/paperless-office/postgres-17/backup_dbdump.sql
  1. Als nächstes den Dokumenten Import
sudo docker-compose exec webserver document_importer ../export
  1. Wenn alles durchgelaufen ist, geht es ans Aufräumen
  • Container paperless-office-postgres-17 stoppen
  • Projekt löschen
  • Über File Editor/Text Editor compose.yaml abändern
    • kompletten db Zweig rauslöschen so daß nur doch db-17 überbleibt
    • dann den db-17 Block so ändern, daß fast alle 17 bzw.“-17” gelöscht werden. Einzig folgende Zeile bleibt mit einer 17
  db:
    image: postgres:17 -> diese 17 bleibt
    container_name: paperless-office-postgres
    restart: always
    environment:
      POSTGRES_DB: xxx
      POSTGRES_USER: xxx
      POSTGRES_PASSWORD: xxx
    volumes:
      - /volume1/docker/paperless-office/postgres:/var/lib/postgresql/data
    user: "xxx"
    networks:
      - paperless-office-network
  1. In die File Station gehen und im paperless-office den Unterordner “postgres” löschen,
  2. Den vorhandenen Order postgres-17 in postgres umbenennen

Als letztes wieder zurück in den Container Manager und das Projekt neu erstellen.
Wenn Ihr wieder den Exit Code 0 seht und alle Container stabil grün, sollte alles passen.

image
Und nach dem Einloggen sah ich auch die Änderungen, die ich kurz zuvor vorgenommen hatte.
Puh geschafft…Datenbank Update und Migration

PS: Ich bin mir nicht sicher, ob es nicht einen effizienteren Weg gibt als den oben Beschriebenen. Muß man immer gleich Projekt löschen? Aber alle meine Versuche, einzeln zu updaten/zu veränderten führten am Ende immer zu Fehlern und ständigen Abstürzen der Datenbank.

EDIT:
Ich hatte oben vergessen, den Import von Dokumenten aufzunehmen.

EDIT2:
Als Docker Anfänger fragte ich mich: in der compose.yaml steht die major Version postgres:17. Aber welche minor Version wird eigentlich genommen. Es gibt mittlerweile davon 4. Aufschluß gibt der SSH Befehl

sudo docker exec -it paperless-office-postgres psql -U paperless -c "SELECT version();"

PostgreSQL 17.4 (Debian 17.4-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit

Moin,

tolle Anleitungen, Respekt.

Ich denke, dass ein Großteil Deiner Arbeit auch auf andere Installationen, zutreffen, nicht nur auf Synology Docker.

Recht herzlichen Dank, dass Du das alles mit uns Teils.

VG
Bernd

1 „Gefällt mir“

Was tun wenn der Container Manager hängt bzw. sich das Projekt einfach nicht stoppen läßt?
Letzter Tipp in dieser kleinen Synology / Container Manager / Paperless Reise

Ich hatte während meines Herumprobierens mehrmals den Fall, daß sich das Container Projekt nicht stoppen ließ, sichtbar am leeren Terminalfenster

Was kann man tun?

  • Ja, NAS durchstarten würde helfen :slight_smile:
  • per SSH (der smarte aber umständlichere Weg)
    • als admin anmelden
    • sudo docker ps → listet alle Docker
    • sudo docker stop paperless-office-webserver
    • sudo docker stop paperless-office-gotenberg
    • sudo docker stop paperless-office-postgres
    • sudo docker stop paperless-office-redis
    • sudo docker stop paperless-office-tika
    • Starten kann man dann wieder mit einem Klick auf Projekt im Container Manager
  • Klar SSH ist toll aber ich hab zu einer kleineren Hammer Methode gegriffen: Paket-Zentrum und Container Manager stoppen → Abwarten → Starten → Abwarten bis Container Manager und Paperless Projekt automatisch starten

Gutes Gelingen!

Meine ersten echten Update Erfahrungen, ein Krampf
Hinweis für Copy/Paste Fans - obiges Bash Script für Aufgabenplaner angepaßt

Heute hatte ich zum ersten Mal neue Updates von Redis und Paperless selbst und nichts ging mehr danach - Postgres und Webserver immer wieder Neustarts.
Erstmal alles gelöscht Hyperbackup restored und die gleichen Probleme weil ich :latest in der compose.yaml zu stehen habe und damit wieder die neuesten Versionen. Immer die gleiche Sch… mit Updates dachte ich mir

  • …aber das Problem war ich selber. Ich hatte diese Woche meine compose.yaml produktiv gemacht mit anderen User und Kennwörtern und keiner Schuld bewußt :innocent:
date stream content
2025/04/10 20:29:01 stderr django.db.utils.OperationalError: connection failed: connection to server at 172.25.0.5, port 5432 failed: FATAL: password authentication failed for user paperless

Ok, ich hatte beim Webserver die Zeilen vertauscht, schluck.

  • Dann habe ich mir den Aufgabenplaner angeschaut und das Bashscript ausgeführt, auch Fehler

[INFO] Leere Dokumenten-Export-Verzeichnis: /volume1/docker/paperless-office/export
[INFO] Starte Dokumenten-Export…

0%| | 0/35 [00:00<?, ?it/s]
43%|████▎ | 15/35 [00:00<00:00, 122.10it/s]
86%|████████▌ | 30/35 [00:00<00:00, 133.25it/s]
100%|██████████| 35/35 [00:00<00:00, 127.67it/s]
[OK] Dokumenten-Export erfolgreich abgeschlossen.
[INFO] Erstelle PostgreSQL-Dump: /var/lib/postgresql/data/backup_dbdump.sql
pg_dump: error: connection to server on socket “/var/run/postgresql/.s.PGSQL.5432” failed: FATAL: database “xxx” does not exist
[ERROR] Fehler beim Datenbank-Dump!

Ok, paperless war nicht der DB Name sondern der Username. Hier das angepaßte Bash Script, wo ich oben per Variable Namen User und DB setze.

Bash script Version 1.1

Zusammenfassung
#!/bin/bash
#Bacardi version 1.1

# === Konfiguration ===
PROJECT_DIR="/volume1/docker/paperless-office"
DOKUMENTE_EXPORT_DIR="$PROJECT_DIR/export"

DB_CONTAINER="paperless-office-postgres"
DB_USER="xxx"
DB_NAME="xxx"
DB_VOLUME_PATH="/var/lib/postgresql/data"
DB_DUMP_FILENAME="backup_dbdump.sql"
DB_DUMP_PATH="$DB_VOLUME_PATH/$DB_DUMP_FILENAME"

# === Export-Verzeichnis prüfen und leeren ===
if [ -n "$DOKUMENTE_EXPORT_DIR" ] && [ -d "$DOKUMENTE_EXPORT_DIR" ]; then
  echo "[INFO] Leere Dokumenten-Export-Verzeichnis: $DOKUMENTE_EXPORT_DIR"
  rm -rf "$DOKUMENTE_EXPORT_DIR"/*
else
  echo "[ERROR] Dokumenten-Export-Verzeichnis existiert nicht. Abbruch."
  exit 1
fi

# === In Projektverzeichnis wechseln ===
cd "$PROJECT_DIR" || { echo "[ERROR] Projektverzeichnis nicht gefunden: $PROJECT_DIR"; exit 1; }

# === Dokumente exportieren ===
echo "[INFO] Starte Dokumenten-Export..."
docker-compose exec -T webserver document_exporter ../export

if [ $? -eq 0 ]; then
  echo "[OK] Dokumenten-Export erfolgreich abgeschlossen."
else
  echo "[ERROR] Fehler beim Dokumenten-Export. Abbruch."
  exit 1
fi

# === PostgreSQL Dump erstellen ===
echo "[INFO] Erstelle PostgreSQL-Dump: $DB_DUMP_PATH"
docker exec "$DB_CONTAINER" pg_dump -U "$DB_USER" -d "$DB_NAME" -F p -f "$DB_DUMP_PATH"

if [ $? -eq 0 ]; then
  echo "[OK] Datenbank-Dump erfolgreich gespeichert unter: $PROJECT_DIR/postgres/$DB_DUMP_FILENAME"
else
  echo "[ERROR] Fehler beim Datenbank-Dump!"
  exit 1
fi

  • Auch der DB Datenimport schlug fehl weil der SQL dump mit Testuser gemacht wurde. ook

Glücklicherweise kann man den Owner im Dump ändern

sed -i 's/OWNER TO alter_user/OWNER TO neuer_user/g' backup_dbdump.sql
und dann
sudo docker exec -it paperless-office-postgres psql -U aktueller_user

Danach ging auch der DB Import wieder.

  • Zuallerletzt der Dokumenten import

/volume1/docker/paperless-office/postgres# sudo docker-compose exec webserver document_importer …/export

Version mismatch: Currently 2.15.1, importing 2.14.7. Continuing, but import may fail.

Checking the manifest
Installed 935 object(s) from 1 fixture(s)
Copy files into paperless…
100%|██████████████████████████████████████████████████████████████████████████████████| 35/35 [00:05<00:00, 6.69it/s]
Updating search index…
100%|██████████████████████████████████████████████████████████████████████████████████| 35/35 [00:00<00:00, 38.45it/s]

Ein letzter Blick auf
image

Und alles war wieder da.

Fazit:
Als Dockeranfänger war der erste Updatedurchlauf ein Krampf und mir ging die ganze Zeit durch den Kopf, wie ich wohl Panik gehabt hätte, wenn schon hunderte Dokumente eingescannt gewesen wären inklusive 80 % der Originale weggeworfen.

Ich mach trotzdem weiter.

EDIT:
Es gab heute in einem anderen Post einen schönen Link von @MelleD wo Docker Befehle zur Fehlersuche gelistet sind. Finde ich hilfreich.