HomeBlogÜber

Papierloses Büro mit DMS Paperless-ngx auf Homeserver

Von Jewgeni
Kategorie: Homeserver
June 02, 2021
Update: January 17, 2023
5 Minuten
Papierloses Büro mit DMS Paperless-ngx auf Homeserver

Inhaltsverzeichnis

01
Benutzer und Verzeichnis erstellen
02
Portainer oder Docker Compose
03
Update
04
Backup
05
Tika / Gotenberg

Ein eigenes Dokumenten-Management-System ist praktisch. Ich möchte Paperless ngx einsetzen. Es ist kostenlos und bietet OCR für hochgeladene Dateien. Ein Dokument bleibt als PDF im angegebenen Verzeichnis gespeichert, damit wird man nicht an Paperless-ngx gebunden.

Paperless ngx wurde im März 2022 als Nachfolger von Paperless-ng released. Seit Paperless-ngx v1.10.0 (November 2022) werden qpdf 11, pikepdf 6 & ocrmypdf 14 genutzt, was die OCR-Qualität verbessert. Außerdem wurde die automatische Zuordnung von Meta-Daten wie Tags verbessert. Mit Paperless-ngv v1.11.0 ist es nun endlich auch möglich nicht nur PDF-Dateien (und mit Hilfe von Tika/Gotenberg auch Office-Dokumente) ins Dokumentenmangement zu laden, sondern es können auch E-Mails verarbeitet werden. Zuvor wurden aus E-Mails nur die Anhänge extrahiert, jetzt wird auch die E-Mail selbst archiviert.

Voraussetzung für diese Anleitung ist, dass Portainer (Portainer mit Traefik oder zumindest Docker-Compose (Docker auf Raspberry Pi) auf dem Server installiert ist. Es funktioniert grundsätzlich sowohl mit einem reinen Ubuntu-Server(Affiliate-Link) oder sowas wie einem Raspberry Pi. Außerdem ist es empfehlenswert mindestens einen GB RAM zu haben.

Möchte man Paperless-ngx auf einem Synology NAS installieren, gibt es hier einen neuen Blogpost mit einer Anleitung.

Benutzer und Verzeichnis erstellen

Zunächst benötigt man eine Docker Gruppe. Diese sollte bereits mit der Installation von Docker vorhanden sein.

# Der eigene User wird der Docker-Gruppe hinzugefügt
sudo gpasswd -a namedesnutzers docker
# Danach kann die User-ID und die Gruppen-ID ausgelesen werden
id namedesnutzers
# Für die Rechteverwaltung kann ACL installiert werden
sudo apt install acl
# Im Home-Verzeichnis wird der Ordner docker erstellt
cd ~
mkdir docker
# Die Gruppe docker erhält alle Rechte am Ordner
sudo setfacl -Rdm g:docker:rwx docker
sudo setfacl -Rm g:docker:rwx docker
sudo chmod -R 775 docker
# Zum Test kann nochmal geschaut werden, ob die Rechte richig gesetzt wurden
getfacl docker

Jetzt hat die Gruppe docker die Rechte am Ordner ~/docker. Der Nutzer kann nun in diesem Ordner Dateien erstellen, bearbeiten und darauf zugreifen. Die Rechte werden automatisch auf die Unterordner übernommen. Die ID des Nutzers (am besten nicht root) und der Gruppe Docker wird noch gebraucht. Zudem erstellen wir ein Verzeichnis für das Programm mit ein paar Unterordnern.

mkdir ~/docker/paperless
cd ~/docker/paperless
mkdir consume
mkdir db
mkdir export
mkdir media
mkdir data

Die Ordnerstruktur sieht nun so aus:

paperless
├── consume
├── data
├── db
├── export
└── media

Natürlich können die Ordner auch an einer anderen Stelle erstellt werden. Die Pfade müssen dann in den Docker-Compose Dateien angepasst werden.

Consume Ordner

In den Consume Ordner können Dateien abgelegt werden, die in man in Paperless verwalten möchte. Das ist insbesondere dann praktisch, wenn man einen Scanner hat, der Zugriff auf das Netzwerk hat und direkt in den consume Ordner scannen kann. Das erspart das manuelle hochladen. Empfehlenswert ist beispielsweise der Brother ADS-1700W (Affiliate-Link) oder sofern auch Dokumente gedruckt werden sollen, der Xerox 6515 DNI (Affiliate-Link).

Data Ordner

Hier befinden sich einige Dateien, die von Paperless gespeichert werden, wie z.B. logs.

DB Ordner

Hier ist die Datenbank.

Export Ordner

Nutzt man den Dokument-Exporter, können hier die Dokumente abgelegt werden.

Media Ordner

Hier werden die Dokumente gespeichert und zwar auch die Originalen. Insbesondere diesen Ordner sollte man sichern, wenn in Paperless wichtige Dokumente verwaltet werden.

Portainer oder Docker Compose

Jetzt kann man entweder zu Portainer wechseln, um einen neuen Stack zu erstellen, alternativ lässt sich auch Docker Compose nutzen, indem man eine docker-compose.yml Datei im Paperless Ordner erstellt.

touch ~/docker/paperless/docker-compose.yml

Neuer Stack (Docker-Compose)

Unter Stacks kann nun ein neuer Stack hinzugefügt werden.

Neuer Stack
Neuer Stack

Hier fügen wir den Docker-Compose Code ein.

Compose Datei in den Stack einfügen
Compose Datei in den Stack einfügen

version: '3.4'
networks:
internal:
external: false
services:
broker:
container_name: paperless-redis
image: redis:6.2
networks:
- internal
restart: unless-stopped
db:
container_name: paperless-db
image: postgres:14
networks:
- internal
restart: unless-stopped
volumes:
- ~/docker/paperless/db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless
webserver:
container_name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:latest
networks:
- paperless_net
- internal
restart: unless-stopped
depends_on:
- db
- broker
ports:
- 8050:8000
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8000']
interval: 30s
timeout: 10s
retries: 5
volumes:
- ~/docker/paperless/data:/usr/src/paperless/data
- ~/docker/paperless/media:/usr/src/paperless/media
- ~/docker/paperless/export:/usr/src/paperless/export
- ~/docker/paperless/consume:/usr/src/paperless/consume
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
USERMAP_UID: 1000
USERMAP_GID: 100
PAPERLESS_OCR_LANGUAGES: eng deu
PAPERLESS_SECRET_KEY: pa6lHUuc1W8PQWdsP6wXViH1cJoKV38zj9ixRkDeTv3Q0iX8O9pNdq9GVXIqH6gilf4uV18vVy5KTeLAvghbkBbZz9ZsF9g5jmx5
PAPERLESS_TIME_ZONE: Europe/Berlin
PAPERLESS_OCR_LANGUAGE: deu
PAPERLESS_FILENAME_FORMAT: '{created_year}/{correspondent}/{title}'
# PAPERLESS_URL: "https://paperless.meinedomain.de"

Geändert werden müssen die Einträge zum Volume, falls sich die zuvor beschriebenen Ordner woanders befinden.

Geändert werden müssen USERMAP_UID und USERMAP_GID, die wir im ersten Schritt ausgelesen haben.

Geändert werden sollte der Port 8050, wenn sich da was anderes bereits befindet. Im diesem Fall zum Beispiel 8020:8000 statt 8050:8000. Die Ports müssen überhaupt nicht veröffentlicht werden, wenn sich ein Reverse Proxy auf demselben Server befindet. In diesem Fall muss der Host als Ziel des Proxy Hosts angegeben werden und der Container muss dem Proxy Netzwerk hinzugefügt werden.

Geändert werden muss der PAPERLESS_SECRET_KEY. Der kann zufällig sein. Wenn man nicht plant Paperless öffentlich zu betreiben, kann man die Zeile auch komplett auskommentieren.

Weitere Konfigurationsmöglichkeiten finden sich in der Dokumentation.

Ohne Portainer muss der Inhalt in die docker-compose.yml eingefügt (nano ~/docker/paperless/docker-compose.yml) und gestartet (docker compose up -d oder docker-compose up -d) werden.

Das Deployment kann etwas Zeit in Anspruch nehmen, wenn alle drei Images bisher noch nicht heruntergeladen wurden. Nach ein bisschen Warten sollten alle drei Container gestartet sein.

Container laufen
Container laufen

Wir besuchen jetzt die IP-Adresse vom Server inklusive Portnummer (also 8050 im oberen Beispiel) aus der Docker-Compose Datei.

Anmeldungsinterface
Anmeldungsinterface

Neuer Benutzer

Wir können uns aber vermutlich noch nicht anmelden, weil kein Benutzer erstellt wurde. Dies erledigen wir auch in Portainer. Dazu drücke ich auf den paperless Container.

Auswahl des Containers
Auswahl des Containers

Anschließend auf Console.

Console
Console

Und dann Connect.

Connect
Connect

Dort führen wir einen Befehl aus, um einen Benutzer anzulegen.

python3 manage.py createsuperuser

Ohne Portainer geht es mit docker exec -it paperless python3 manage.py createsuperuser.

Es muss ein Benutzername, eine E-Mail-Adresse und ein Passwort eingegeben werden. Jetzt sollte es auch möglich sein sich anzumelden.

Dashboard
Dashboard

Update

Gegebenenfalls möchte man seine Paperless Instanz auf den neuesten Stand bringen (Changelog).

Die aktuell installierte Version sieht man unten links in der Paperless-ng UI. In meinem Fall ist es Version 1.4.4, obwohl bereits 1.5 existiert.

Version
Version

Vor dem Update empfehle ich eine Sicherung zu erstellen.

Update über CLI

Über den CLI (ohne Portainer) lässt sich das Update relativ einfach durchführen.

docker compose pull
docker compose down
docker compose up -d

Möchte man eine höhere Postgres oder Redis Version nutzen (nicht empfohlen), muss man die Angaben auch in der docker-compose Datei anpassen. Die Datenbankversion sollte man nicht einfach von 13 auf 14 oder von 14 auf 15 erhöhen, das kann dazu führen, dass sie nicht mehr geladen wird.

Update über Portainer

Doch auch mit Portainer lässt sich das Update einfach bewerkstelligen. Dazu muss zunächst die Image-Seite aufgerufen werden.

Portainer Images
Portainer Images

Dort gebe ich das Image ein, welches ich erneut pullen möchte.

Images pullen
Images pullen

Es sind laut der Docker-Compose Datei folgende Images notwendig:

  • ghcr.io/paperless-ngx/paperless-ngx:latest
  • postgres:14
  • redis:6.2

Bei Paperless kann der Download etwas dauern, da über ein 1 GB heruntergeladen werden. Bei den Images sehe ich nun jeweils zwei Stück (außer es gab keine neuere Version).

Doppeltes Image
Doppeltes Image

Auch hier ist es so, wenn ich statt Postgres Version 13.x lieber 14.x (nicht empfohlen) nutzen möchte, muss ich das im Stack Editor anpassen. Im Stack Menü stoppe ich den Paperless Stack.

Stack stoppen und wieder starten
Stack stoppen und wieder starten

Danach starte ich ihn gleich wieder. Damit habe ich soeben mein Paperless (sowie auch Redis und Postgre) aktualisiert.

Neue Version
Neue Version

Backup

Gelegentlich ist es sinnvoll eine Sicherungskopie von Paperless zu erstellen. Dazu sollte der Paperless Ordner auf ein externes Gerät geschoben werden. Beim Ordner “db” könnte das jedoch spätestens bei der Wiederherstellung zu Problemen führen. Hier ist es empfehlenswert einen Dump der Datenbank auszuführen.

Dazu verbinde ich mich zunächst mit meinem PostgreSQL Container.

Postgres
Postgres

Über Portainer muss dazu /bin/bash im Container mit der Datenbank ausgeführt werden

Ohne Portainer ist es natürlich auch möglich:

docker exec -i paperless-db /bin/bash

Im Container navigieren wir dann zum Ordner mit den Daten, die wir persistent gemountet haben.

cd var/lib/postgresql/data

Jetzt muss nur noch der Dump erstellt werden. Gegebenenfalls müssen Benutzername (paperless) und Passwort (paperless) angepasst werden.

pg_dump --username paperless paperless > dump.sql
exit

Daraufhin scheint es vielleicht so als wäre nichts passiert, aber im Ordner […]/paperless/db befindet sich eine Datei namens „dump.sql“.

File-Explorer
File-Explorer

Diese sollte gesichert werden. Bei der Wiederherstellung legen wir die dump.sql in den db Ordner und führen danach im DB-Container folgende Befehle aus:

cd /var/lib/postgresql/data
psql --username paperless paperless < dump.sql
exit

In den Kommentaren wurde ich darauf hingewiesen (vielen Dank dafür), dass der Backup-Prozess auch automatisiert werden kann. Dazu muss man widerum den Stack (bzw. die Docker-Compose Datei) um ein weiteres Service erweitern, vorher aber einen Ordner für die Backups erstellen.

mkdir db-backup

Neuer Backup Ordner
Neuer Backup Ordner

version: '3.4'
networks:
internal:
external: false
services:
broker:
container_name: paperless-redis
image: redis:6.2
networks:
- internal
restart: unless-stopped
db:
container_name: paperless-db
image: postgres:14
networks:
- internal
restart: unless-stopped
volumes:
- ~/docker/paperless/db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless
webserver:
container_name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:latest
networks:
- paperless_net
- internal
restart: unless-stopped
depends_on:
- db
- broker
ports:
- 8050:8000
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8000']
interval: 30s
timeout: 10s
retries: 5
volumes:
- ~/docker/paperless/data:/usr/src/paperless/data
- ~/docker/paperless/media:/usr/src/paperless/media
- ~/docker/paperless/export:/usr/src/paperless/export
- ~/docker/paperless/consume:/usr/src/paperless/consume
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
USERMAP_UID: 1000
USERMAP_GID: 100
PAPERLESS_OCR_LANGUAGES: eng deu
PAPERLESS_SECRET_KEY: pa6lHUuc1W8PQWdsP6wXViH1cJoKV38zj9ixRkDeTv3Q0iX8O9pNdq9GVXIqH6gilf4uV18vVy5KTeLAvghbkBbZz9ZsF9g5jmx5
PAPERLESS_TIME_ZONE: Europe/Berlin
PAPERLESS_OCR_LANGUAGE: deu
PAPERLESS_FILENAME_FORMAT: '{created_year}/{correspondent}/{title}'
PAPERLESS_URL: 'https://paperless.meinedomain.de'
db-backup:
container_name: paperless-db-backup
image: postgres:14
volumes:
- ~/docker/paperless/db-backup:/dump
- /etc/localtime:/etc/localtime:ro
environment:
PGHOST: db
PGDATABASE: paperless
PGUSER: paperless
PGPASSWORD: paperless
BACKUP_NUM_KEEP: 10
BACKUP_FREQUENCY: 7d
entrypoint: |
bash -c 'bash -s <<EOF
trap "break;exit" SIGHUP SIGINT SIGTERM
sleep 2m
while /bin/true; do
pg_dump -Fc > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.psql
(ls -t /dump/dump*.psql|head -n $$BACKUP_NUM_KEEP;ls /dump/dump*.psql)|sort|uniq -u|xargs rm -- {}
sleep $$BACKUP_FREQUENCY
done
EOF'
networks:
- internal

So bekommt man jede Woche ein neues Backup der Datenbank.

Dump im neuen Verzeichnis
Dump im neuen Verzeichnis

Tika / Gotenberg

Paperless kann in der oben ausgeführten Konfiguration keine “Office”-Dateien, wie zum Beispiel “.doc”, “.xlsx” und “.odt” verarbeiten, sondern nur PDFs. Versucht man eine Word-Datei in die Dokumentenverwaltung hochzuladen, erscheint eine Fehlermeldung. Mithilfe von Tika und Gotenberg ist es möglich diese Dateitypen während des Uploads in PDF-Dateien zu konvertieren.

Nachteil: Die zusätzlichen Dienste verbrauchen Systemressourcen. Hat man nur 1-2 GB RAM, kann es mit dem Arbeitsspeicher kanpp werden.

Paperless-Stack mit Tika und Gotenberg
Paperless-Stack mit Tika und Gotenberg

Die Änderung ist einfach eingerichtet. Es muss nur die Docker-Compose Datei mal wieder verändert werden:

version: '3.4'
networks:
internal:
external: false
services:
broker:
container_name: paperless-redis
image: redis:6.2
networks:
- internal
restart: unless-stopped
db:
container_name: paperless-db
image: postgres:14
networks:
- internal
restart: unless-stopped
volumes:
- ~/docker/paperless/db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: einPasswort
webserver:
container_name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:latest
networks:
- internal
restart: unless-stopped
depends_on:
- db
- broker
ports:
- 8050:8000
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8000']
interval: 30s
timeout: 10s
retries: 5
volumes:
- ~/docker/paperless/data:/usr/src/paperless/data
- ~/docker/paperless/media:/usr/src/paperless/media
- ~/docker/paperless/export:/usr/src/paperless/export
- ~/docker/paperless/consume:/usr/src/paperless/consume
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBPASS: einPasswort
USERMAP_UID: 1000
USERMAP_GID: 100
PAPERLESS_OCR_LANGUAGES: eng deu
PAPERLESS_SECRET_KEY: pa6lHUuc1W8PQWdsP6wXViH1cJoKV38zj9ixRkDeTv3Q0iX8O9pNdq9GVXIqH6gilf4uV18vVy5KTeLAvghbkBbZz9ZsF9g5jmx5
PAPERLESS_ALLOWED_HOSTS: 'localhost,paperless.domain.de'
PAPERLESS_TIME_ZONE: Europe/Berlin
PAPERLESS_OCR_LANGUAGE: deu
PAPERLESS_FILENAME_FORMAT: '{created_year}/{correspondent}/{title}'
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000/forms/libreoffice/convert#
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
PAPERLESS_URL: 'https://paperless.meinedomain.de'
db-backup:
container_name: paperless-db-backup
image: postgres:14
volumes:
- ~/docker/paperless/db-backup:/dump
- /etc/localtime:/etc/localtime:ro
environment:
PGHOST: db
PGDATABASE: paperless
PGUSER: paperless
PGPASSWORD: paperless
BACKUP_NUM_KEEP: 10
BACKUP_FREQUENCY: 7d
entrypoint: |
bash -c 'bash -s <<EOF
trap "break;exit" SIGHUP SIGINT SIGTERM
sleep 2m
while /bin/true; do
pg_dump -Fc > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.psql
(ls -t /dump/dump*.psql|head -n $$BACKUP_NUM_KEEP;ls /dump/dump*.psql)|sort|uniq -u|xargs rm -- {}
sleep $$BACKUP_FREQUENCY
done
EOF'
networks:
- internal
gotenberg:
image: gotenberg/gotenberg:7
restart: unless-stopped
environment:
CHROMIUM_DISABLE_ROUTES: 1
command:
- 'gotenberg'
- '--chromium-disable-javascript=true'
- '--chromium-allow-list=file:///tmp/.*'
networks:
- internal
tika:
image: apache/tika:2.3.0
restart: unless-stopped
networks:
- internal

Hat man jedoch eine ARM-CPU benötigt man andere Images.

Bei Fragen / Anmerkungen / Verbesserungsvorschlägen usw. freue ich mich über Kommentare :)


Tags

#anleitung#dms#docker#homeserver#nas#paperless#portainer#server#synology
Vorheriger Blogpost
Git - Harter Reset auf alte Version
Nächster Blogpost
VPS - Benchmark Test

Kategorien

Aktuelles
Excel
Finanzen
Gaming
Gatsby
Git
Google
Homeserver
Server
Tailwind
Werbung

Inhaltsverzeichnis

1
Benutzer und Verzeichnis erstellen
2
Portainer oder Docker Compose
3
Update
4
Backup
5
Tika / Gotenberg

Related Posts

Vaultwarden mit Docker auf einem Synology NAS
May 04, 2023
May 06, 2023
3 min

Links

KontaktÜber

Social Media