Paperless NGX: Separater Datenbankserver und Migration
Einleitung
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.
Ausgangssituation
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.
Vorbereitung
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
docker ps
Abriss der alten Umgebung
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
docker image prune -a
rm -R data media
Aufbau und Einrichtung des Datenbankservers
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
nano docker-compose.yml
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:
docker compose up -d
docker ps
docker logs pgredis-postgres-1
docker logs pgredis-redis-1
docker ps
Aufbau von Paperless-NGX
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
rm -R data media
mv data dataold && mv media mediaold
nano docker-compose.yml
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
Wenn das soweit vorbereitet ist, dann kann nun Paperless-NGX mit
sudo systemctl restart fail2ban
docker compose up -d
Migration/Import der Daten
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: nachsehen, was fail2ban schon so alles erkannt und blockiert hat. Die Ausgabe sieht dann in etwa so aus:
ssh -l benutzername IP-des_neuen_Servers
cd paperless-ngx
rsync -avE -e ssh export/ {Benutzername}@IP_des_neuen_Servers:/home/{Benutzername}/paperless-ngx/export
Wenn die Altdaten im Order export liegen, dann kann der Import mit
docker exec -it paperless-webserver document_importer /usr/src/paperless/export
Migration mit Update von Paperless-NGX
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
docker compose up -d
docker compose down
docker compose up -d