Mitunter tauchen in Foren Hilferufe auf, dass die Datenbank, die Paperless NGX zugrunde liegt, aktualisiert werden muss. Das heißt natürlich, das Datenbankmanagementsystem (DBMS). Wenn man alles per Docker und Docker Compose installiert hat, dann könnte man auf die Idee kommen, einfach die Versionsnummern in der entsprechenden Datei docker-compose.yml zu ändern. Das kann aber zu Kompatibilitätsproblemen mit den bestehenden Daten führen. Die neue Datenbank kann die alten Datenbankeinträge nicht lesen. Ein zuverlässiger Weg besteht darin, zunächst alles mit dem Exporter zu exportieren, ein frisches System aufzubauen und dann mit dem Importer wieder alles einzulesen. Der Exporter lagert alle Dokumente im hochgeladenen Original, in der PDF-Repräsentation und als Webvorschaubild aus. Außerdem erzeugt er eine Datei namens manifest.json, in der alle Metadaten der Dokumente im JSON-Format gespeichert sind und eine Datei metadata.json, in der die Versionsnummer der verwendeten Paperless-NGX-Installatiion steht. Damit kann man einen Import in eine kompatible Nextcloud-Installation vornehmen. Das kann man auch verwenden, um das DBMS komplett zu wechseln.
Paperless NGX besteht aus einem Webserver, einer Datenbank (Postgresql oder MariaDB, bzw. MySQL), einer In-Memory-Datenbank namens Redis und den Komponenten Gotenberg und Tika zur Verarbeitung verschiedener Formate. Im Standard laufen alle diese Komponenten als Container auf einem Server und für die allermeisten Anwendungsfälle dürfte das auch absolut in Ordnung sein. Allerdings könnte die Systemlast den Server bei intensiver Nutzung mit großen Datenbeständen und vielen Anwenderinnen und Anwendern möglicherweise überfordern. Dann wäre es gut, die Last auf mehrere Systeme zu verteilen. Dazu bietet es sich an, die Datenbank-Komponenten auf einem separaten Server zu betreiben. Daher zeige ich hier auf, wie ich ein bestehendes System entsprechend auf zwei Server aufteile und die Daten auf die neue Infrastruktur migriere.
Gegeben sei ein Server, der entsprechend der gängigen Empfehlungen (z.B. auch hier in meinem Youtube-Video dazu: Paperless-NGX installieren, Backup und Restore) eingerichtet wurde. Das heißt, es gibt eine docker-compose.yml, in der alle Container definiert werden. Die Dokumente liegen in Verzeichnissen unterhalb des media-Verzeichnisses und die Datenbank liegt in Dateien innerhalb des Verzeichnisses data. Am einfachsten wäre es, ein komplett neues System auf einem neuen Server aufzubauen. Wenn das nicht geht, dann muss man den Mut aufbringen, das Altsystem größtenteils zu löschen. An der Stelle sei noch einmal die Bedeutung von Datensicherung hervorgehoben.
Im Folgenden gehe ich von einem Anwendungsserver mit der IP-Adresse 192.168.0.33 und einem Datenbankserver mit der IP-Adresse 192.168.0.34 aus.
Zu allererst muss man einen aktuellen Export der Daten und Strukturen anstoßen. Dazu meldet man sich auf der Konsole des (Alt-)Servers an und stößt einen aktuellen Export an mit
docker exec -it paperless-webserver-1 document_exporter /usr/src/paperless/export
Dabei muss natürlich der richtige Containername, hier paperless-webserver-1 gewählt werden. Wie der im Einzelfall wirklich heißt, kann man sich mit dem Befehl
docker ps
ausgeben lassen. Wenn es hierbei keine Fehlermeldung gibt, dann sollte im Export-Verzeichnis (das in meinem Fall ein Unterverzeichnis des Verzeichnisses paperless-ngx im Homeshare ist), ein aktualisierter Export liegen. Wenn man das regelmäßig zu Datensicherungszwecken macht, dann wird nur das Delta exportiert und die Metadatendateien neu erstellt. Das sollte nicht so lange dauern. Achtung: Die so exportierten Daten können nur in eine neue Umgebung mit der halbwegs identischen Paperless-NGX-Version eingelesen werden. Will man im Rahmen dieser Änderung hier die Paperless-NGX-Version anheben, dann sollte man zunächst die Migration mit der gleichen Version durchführen und das Update anschließend.
Wenn man nicht auf einen neuen Server wechseln kann oder möchte, dann muss man nun die alte Umgebung zunächst tilgen. Man wechselt in das Verzeichnis mit der docker-compose.yml und beendet die entsprechenden Container mit dem Befehl
docker compose down
Dann räumt man die verwaisten Images mit dem Befehl
docker image prune -a
auf. Damit werden Docker-Images gelöscht, die keinem laufenden Container mehr zugeordnet sind. Anschließend löscht man die Verzeichnisse data und media im Ordner paperless-ngx mit dem Befehl
rm -R data media
Nun ist die alte Umgebung weg. Jetzt erst an eine Datensicherung zu denken, wäre etwas zu spät.
Nun geht es daran, die Datenbank auf dem zweiten Server einzurichten. Eine abgesetzte Datenbankumgebung auf dem selben Server wie das Restsystem wäre ja sinnlos. Ich gehe also davon aus, dass ein neuer Server mit Docker und Docker Compose zur Verfügung steht. Hier erstelle ich nun im Homeshare ein neues Verzeichnis, dem ich einen beliebigen Namen geben kann. Ich wähle "pgredis" dafür. Ich erstelle den Ordner und wechsele sofort dort hinein.
mkdir pgredis && cd pgredis
Dann erstelle ich mit
nano docker-compose.yml
eine neue Datei mit folgendem Inhalt:
services:
postgres:
image: postgres:alpine
environment:
POSTGRES_DB: paperless2
POSTGRES_PASSWORD: 123456
POSTGRES_USER: paperless
ports:
- 5435:5432
restart: unless-stopped
networks:
- redis-network
volumes:
- ./pgdata:/var/lib/postgresql/data # Named Volume
redis:
image: redis:8.4
command: redis-server
volumes:
- ./redis_daten:/var/lib/redis
- ./redis_config:/usr/local/etc/redis/redis.conf
ports:
- 6379:6379
restart: unless-stopped
networks:
- redis-network
networks:
redis-network:
driver: bridge
volumes:
pgdata:
redis_daten:
redis_config:
Dass 123456 kein geeignetes Passwort ist, muss ich wohl nicht erwähnen. Hier werden die Services postgres und redis definiert. Mit den environment-Parametern im Servicesektor postgres werden die Datenbank, der Datenbankuser und sein Passwort definiert. Die Volume-Definitionen bewirken, dass persistente Volumes erzeugt werden, die nach einem Neustart der Container und auch der Server noch erhalten bleiben. So bleiben vor allem auch die Datenbankeinträge erhalten. Schließlich wird ein Netzwerk redis-network definiert, damit sich die Container im selben Docker-Netzwerk befinden und sich gegenseitig auch finden. Dieses Netzwerk wird beim Start der Container erzeugt, wenn es noch nicht vorhanden ist. Mit
docker compose up -d
werden die Container gestartet. Den Erfolg kann man sich nach wenigen Sekunden mit
docker ps
ansehen und ggf. mit
docker logs pgredis-postgres-1
und
docker logs pgredis-redis-1
überprüfen. Wenn man das Verzeichnis, in dem die Datei docker-compose.yml liegt, anders benannt hat, dann heißen natürlich auch die Container anders. Die kann man sich mit
docker ps
anzeigen lassen.
Nachdem nun die Datenbanksysteme am Start sind, sind die Container für Paperless-NGX an der Reihe. Ich logge (wieder) mich auf der SSH-Konsole des Paperless-NGX-Servers ein und wechsele in den Ordner paperless-ngx. Bei Aufbau eines neuen Systems, auf dem bisher Paperless-NGX nicht lief, muss der Ordner natürlich erst erstellt werden.
cd paperless-ngx
Dann lösche ich die vorhandenen Verzeichnisse data und media mit
rm -R data media
Wer sich das nicht traut, kann sie auch einfach umbenennen mit
mv data dataold
mv media mediaold
Das setzt aber voraus, dass der Speicherplatz auf dem Server für die doppelte Datenmenge ausreicht. Dann erstelle ich mit
nano docker-compose.yml
eine neue Compose-Datei mit folgendem Inhalt:
services:
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:2.19.1
container_name: paperless-webserver
restart: unless-stopped
depends_on:
- gotenberg
- tika
ports:
- "8000:8000"
volumes:
- ./data:/usr/src/paperless/data
- ./media:/usr/src/paperless/media
- ./export:/usr/src/paperless/export
- ./consume:/usr/src/paperless/consume
environment:
PAPERLESS_URL: "domain oder leer lassen"
PAPERLESS_TIME_ZONE: Europe/Berlin
PAPERLESS_OCR_LANGUAGE: deu+eng
PAPERLESS_SECRET_KEY: "komplexes Passwort"
PAPERLESS_REDIS: redis://192.168.0.34:6379
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_DBHOST: 192.168.0.34
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless
PAPERLESS_DBPASS: 123456
PAPERLESS_DBPORT: 5435
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
gotenberg:
image: docker.io/gotenberg/gotenberg:8.24
restart: unless-stopped
# The gotenberg chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even javascript.
command:
- "gotenberg"
- "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*"
tika:
image: docker.io/apache/tika:latest
restart: unless-stopped
Hier wird also ein Paperless-Webserver in der Version 2.19.1 erstellt. Wer zum Zwecke der Migration aus einem Alt-System zunächst eine andere Version braucht, ändert das hier natürlich ab. Relevant sind hier die Einträge für die Verbindung zu den Datenbank-Komponenten Redis und Postgresql. Die Datenbank-Parameter entsprechen natürlich denen in der weiter oben aufgeführten Docker-Compose-Datei. Ansonsten ändern sich gegenüber der früheren Definition die weiteren Einträge nicht. Die Unterverzeichnisse data, media, export und consume werden persistent gemountet. Gotenberg und Tika werden zur Verarbeitung diverser Dateiformate geladen.
Wenn das soweit vorbereitet ist, dann kann nun Paperless-NGX mit
docker compose up -d
gestartet werden.
Die (hoffentlich) zuvor exportierten Dokumente und Daten können nun unter Verwendung des Importers wieder eingelesen werden. Wenn man auf einem neuen Server neu anfängt, dann muss man zunächst die Daten in das Exportverzeichnis auf dem neuen Server übertragen. Dazu kann man das Kommandozeilentool rsync verwenden. Zunächst muss eine SSH-Verbindung zwischen dem alten und dem neuen Server möglich sein. Das testet man, indem man auf dem alten Server auf der Konsole eingibt:
ssh -l benutzername@IP-des_neuen_Servers
Ggf. wird man zunächst gefragt, ob man den SSH-Fingerabdruck des neuen Servers akzeptieren möchte, was man natürlich bestätigen muss. Dann wird man nach dem Passwort des gewählten Benutzers auf dem neuen Server gefragt. Sollte man die Passwort-Authentifizierung deaktiviert haben (s. Tutorial: Server absichern), dann muss man zunächst den öffentlichen Schlüssel des alten Servers auf dem Neuen unter ~/.ssh/authorized_keys eintragen. Wenn der Zugang vom alten auf den neuen Server funktioniert, dann kann man (nachdem man sich ggf. vom neuen Server wieder abgemeldet hat) auf der Konsole des alten Servers eingeben:
cd paperless-ngxrsync -avE -e ssh export/ {Benutzername}@IP_des_neuen_Servers:/home/{Benutzername}/paperless-ngx/export
Damit werden die Dateien aus dem Verzeichnis ~/paperless-ngx/export in das Äquivalent auf dem neuen Server übertragen. Mit den Parametern -avE wird definiert, dass etwaige Archiv-Bits unverändert mit übertragen werden, dass etwaige Ausführbarkeiten ebenfalls unverändert bleiben und dass der Fortschritt ausführlich am Bildschirm ausgegeben wird.
Wenn die Altdaten im Order export liegen, dann kann der Import mit
docker exec -it paperless-webserver document_importer /usr/src/paperless/export
gestartet werden. Hier muss natürlich ggf. der Name des Webserver-Containers angepasst werden. Wenn hierbei keine Fehler aufgetreten sind, dann sollte nun Paperless-NGX wieder einsatzbereit sein und für die Datenbank den dafür vorgesehenen Server nutzen.
Grundsätzlich kann man mit dem Exporter und dem Importer unabhängig von der verwendeten Datenbankversion migrieren. Das kann sogar explizit zum Updaten der Datenbank genutzt werden. Einfach alles exportieren, dann eine neue DB-Version durch Anpassung der Versionsnummer im File docker-compose.yml für die Datenbank eintragen, Container neu starten und Daten wieder importieren. Allerdings gelingt ein Import immer nur mit Daten, die aus einer kompatiblen Version des Webservers exportiert wurden. Wenn ich also zusammen mit der Datenbank auch die Version von Paperless-NGX ändern möchte, dann muss ich zunächst eine kompatible Version von Paperless-NGX in der docker-compose.yml definieren mit der expliziten Angabe der benötigten Version im Image-Tag z.B. wie folgt:
image: ghcr.io/paperless-ngx/paperless-ngx:2.10.1
Dann starte ich den Container mit
docker compose up -d
importiere mit vorgenanntem Befehl die Daten und fahre den Container wieder herunter mit
docker compose down
Danach ändere ich in der Datei docker-compose,yml die Versionsnummer und starte die Container wieder erneut mit
docker compose up -d
Danach läuft Paperless-NGX in der neuen Version. Das heißt, der Import der Daten gelingt mit einer neuen Datenbankversion aber nur mit einer kompatiblen Version des Paperless-NGX-Webservers. Nach Import der Daten kann die Version des Webservers angehoben werden, was dann mit einem Neustart der Container wirksam wird.