Paperless-ngx Bare Metal auf AlmaLinux 10.x installieren

Anleitung, wie man Paperless-ngx Bare Metal (ohne Docker) auf einem AlmaLinux 10.x System einrichtet und konfiguriert

Voraussetzungen

Zuerst wird das EPEL-Repo benötigt. Falls dieses noch nicht installiert ist mit folgenden Befehlen installieren

dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
dnf install https://rpms.remirepo.net/enterprise/remi-release-10.rpm

Dann können die benötigten Basis-Pakete installiert werden:

dnf install ghostscript gnupg libxml2 pkg-config poppler-utils python3 python3-pip python3-setuptools python3-wheel qpdf unpaper mariadb-connector-c-devel liberation-fonts lcms2 ImageMagick leptonica leptonica-devel make gcc file-devel postgresql-devel zbar python3-devel tesseract zlib valkey
dnf install https://ge.mirror.cloud9.ge/epel/9/Everything/x86_64/Packages/p/pngquant-2.17.0-2.el9.x86_64.rpm
dnf install libjpeg-turbo-devel libpng-devel
dnf install cairo-devel pango-devel

valkey muss beim booten gestartet werden:

systemctl enable valkey.service
systemctl start valkey.service

Nun die tesseract (OCR) Trainingsdaten aktualisieren, ggf. für weitere Sprachen:

curl -L -o /usr/share/tesseract/tessdata/osd.traineddata https://github.com/tesseract-ocr/tessdata/raw/main/osd.traineddata
curl -L -o /usr/share/tesseract/tessdata/deu.traineddata https://github.com/tesseract-ocr/tessdata/raw/main/deu.traineddata
curl -L -o /usr/share/tesseract/tessdata/eng.traineddata https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddatac
chmod 644 /usr/share/tesseract/tessdata/{deu,eng,osd}.traineddata
tesseract --list-langs

Paperless-ngx installieren

Zuerst einen Benutzer erstellen

sudo useradd --system --home-dir /opt/paperless --create-home --shell /sbin/nologin paperless

Danach kann Paperless-ngx heruntergeladen, ins Home-Directory entpackt und mit korrekten Berechtigungen versehen werden, Versionsnummer ggf. anpassen:

curl -L -O https://github.com/paperless-ngx/paperless-ngx/releases/download/v2.20.10/paperless-ngx-v2.20.10.tar.xz
tar -xvf paperless-ngx-v2.20.10.tar.xz
cp -r paperless-ngx/* /opt/paperless/
chown -R paperless:paperless /opt/paperless
mkdir -p /opt/paperless/{data,media,consume}
chown -R paperless:paperless /opt/paperless

Nun kann eine minimale Konfiguration erstellt werden. Diese unter /opt/paperless/paperless.conf ablegen (existiert bereits mit auskommentierten Zeilen, die Datei kann einfach unten ergänzt werden).

PAPERLESS_REDIS=redis://localhost:6379

PAPERLESS_DBENGINE=sqlite

PAPERLESS_CONSUMPTION_DIR=/opt/paperless/consume
PAPERLESS_DATA_DIR=/opt/paperless/data
PAPERLESS_MEDIA_ROOT=/opt/paperless/media

PAPERLESS_OCR_LANGUAGE=deu
PAPERLESS_TIME_ZONE=Europe/Zurich

PAPERLESS_SECRET_KEY=0d615b5e11eba5ff3f1b7136dafd27dc63565ef9e42494b35094c07cee6d34de

#PAPERLESS_FILENAME_FORMAT={{ created_year }}/{{ created_month }}/{{ correspondent }}/{{ created }}-{{ title }}

#PAPERLESS_DEBUG=true

Dazu einige Anmerkungen:

  • Das Secret sollte angepasst werden. Ein 32-Bit Hex-String (64 Zeichen) lässt sich beispielsweise mit openssl rand -hex 32 erstellen.
  • PAPERLESS_FILENAME_FORMAT definiert die Struktur des Archivs. Hier ein Jahres, Monat und Korrespondent-Ordner. Wie man bei einer nachträglichen Anpassung die bestehenden Dokumente umbenennt zeige ich am Ende der Doku
  • Debug sollte natürlich nur bei Bedarf aktiviert werden.

Nun müssen noch die Python3 Abhängigkeiten installiert werden:

sudo -u paperless pip3 install --user -r /opt/paperless/requirements.txt

Warnungen können dabei ignoriert werden, es gibt einige Warnungen bezüglich PATH.

Nun können die Einstellungen migriert werden:

cd /opt/paperless/src
sudo -u paperless python3 manage.py migrate

Paperless-ngx ist nun bereit und kann probeweise mit

cd /opt/paperless/src
sudo -u paperless python3 manage.py runserver

gestartet werden. Das startet auf 127.0.0.1:8000 (nur localhost, ggf. tunneln). Man sollte die Admin-Registrierung sehen. Nichts machen und mit Ctrl+C abbrechen.

Paperless-ngx als Dienst einrichten

Damit alle Dienste von Paperless automatisch starten, müssen vier systemd-Dienste erstellt werden. Folgende Dateien erstellen:

/etc/systemd/system/paperless-webserver.service

[Unit]
Description=Paperless Webserver
After=network.target

[Service]
User=paperless
Group=paperless
WorkingDirectory=/opt/paperless/src
EnvironmentFile=/opt/paperless/paperless.conf
ExecStart=/opt/paperless/.local/bin/granian --interface asgi paperless.asgi:application --host 0.0.0.0 --port 8000 --log-level debug --access-log
Restart=always

[Install]
WantedBy=multi-user.target

/etc/systemd/system/paperless-consumer.service

[Unit]
Description=Paperless Consumer
After=network.target

[Service]
User=paperless
Group=paperless
WorkingDirectory=/opt/paperless/src
EnvironmentFile=/opt/paperless/paperless.conf
ExecStart=/usr/bin/python3 manage.py document_consumer
Restart=always

[Install]
WantedBy=multi-user.target

/etc/systemd/system/paperless-task-queue.service

[Unit]
Description=Paperless Celery Worker
After=network.target

[Service]
User=paperless
Group=paperless
WorkingDirectory=/opt/paperless/src
EnvironmentFile=/opt/paperless/paperless.conf
ExecStart=/opt/paperless/.local/bin/celery -A paperless worker --loglevel=INFO
Restart=always

[Install]
WantedBy=multi-user.target

/etc/systemd/system/paperless-scheduler.service

[Unit]
Description=Paperless Scheduler
After=network.target

[Service]
User=paperless
Group=paperless
WorkingDirectory=/opt/paperless/src
EnvironmentFile=/opt/paperless/paperless.conf
ExecStart=/opt/paperless/.local/bin/celery -A paperless beat --loglevel=INFO
Restart=always

[Install]
WantedBy=multi-user.target

Danach können die Dienste aktiviert und gestartet werden:

systemctl daemon-reload
systemctl enable --now paperless-webserver
systemctl enable --now paperless-consumer
systemctl enable --now paperless-task-queue
systemctl enable --now paperless-scheduler

Paperless-ngx steht nun unter Port 8000 via HTTP zur Verfügung. Ein HTTPS Reverse-Proxy ist natürlich empfohlen. Dies kann beispielsweise mit caddy erfolgen, dann paperless-webserver auf 127.0.0.1 binden und Port 8000 tunneln. Eine kleine Anleitung zu Caddy unter AlmaLinux habe ich ebenfalls erstellt.

Nach einer Konfigurations-Anpassung können alle Dienste mit folgendem Kommando neu gestartet werden:

systemctl restart paperless-task-queue paperless-scheduler paperless-consumer paperless-webserver

Classifier prüfen

Die importierten Dokumente werden normalerweise automatisch klassifiziert. Dies klappt nicht immer. Deshalb sollte - nach einigen Stunden Betrieb - das Log geprüft werden.

journalctl -u paperless-task-queue -n 1000 --no-pager | grep -i classifier

Hier die Meldung anschauen, die entweder

[WARNING] [paperless.tasks] Classifier error:

oder

[INFO] [paperless.classifier] No updates since last training

sei sollte. Im zweiten Fall ist alles in Ordnung und es muss nichts weiteres unternommen werden. Im ersten Fall mit dem "Classifier error" müssen wahrscheinlich die nltk_data aufgebaut werden. Dazu sind folgende Befehle notwendig:

sudo mkdir -p /usr/share/nltk_data
sudo chown paperless:paperless /usr/share/nltk_data

sudo -Hu paperless python3 -m nltk.downloader -d /usr/share/nltk_data stopwords
sudo -Hu paperless python3 -m nltk.downloader -d /usr/share/nltk_data snowball_data
sudo -Hu paperless python3 -m nltk.downloader -d /usr/share/nltk_data punkt
sudo -Hu paperless python3 -m nltk.downloader -d /usr/share/nltk_data punkt_tab

Danach kann der Index neu aufgebaut werden:

sudo -Hu paperless python3 /opt/paperless/src/manage.py document_create_classifier

Ist alles erfolgreich, die Logfiles nach ein paar Stunden erneut kontrollieren.

Tuning und Tipps

ImageMagik Policies zum Speicherverbrauch

Die Datei /etc/ImageMagick-7/policy.xml editieren und am Ende (vor abschliessendem Root-Tag) folgende Zeilen einfügen:

<policy domain="coder" rights="read|write" pattern="PDF" />
<policy domain="resource" name="memory" value="1GiB"/>
<policy domain="resource" name="map" value="2GiB"/>
<policy domain="resource" name="disk" value="8GiB"/>
<policy domain="resource" name="area" value="1GiB"/>

jbig2enc für kompaktere PDFs

dnf install git gcc gcc-c++ make automake autoconf libtool
cd /tmp
git clone https://github.com/agl/jbig2enc
cd jbig2enc
./autogen.sh
./configure
make
make install

Workers/Threads limitieren

Für ein Home-Use System mit limitiertem RAM/CPU sind folgende Werte empfohlen. Je grösser die Umgebung, desto mehr Prozesse sollten erlaubt werden. In der /opt/paperless/paperless.conf folgende Zeilen ergänzen:

PAPERLESS_TASK_WORKERS=2
PAPERLESS_THREADS_PER_WORKER=1

Archiv exportieren

Mit folgendem Befehl wird das Archiv nach /backup gesichert.

cd /opt/paperless/src
sudo -u paperless python3 manage.py document_exporter -f /backup

PDF interne Ablage umbenennen

Wenn die Variable PAPERLESS_FILENAME_FORMAT verändert wird gilt das nur für neue Dokumente. Um alle bestehenden Dokumente neu zu benennen, ist folgender Befehl notwendig.

cd /opt/paperless/src
sudo -u paperless python3 manage.py document_renamer

Weitere Infos und Download