E7 · Paperless v3 Neustart — Design¶
Datum: 2026-09-19
Epic: homeserver#190 (dazu #87, #242)
Status: Design abgestimmt mit Robin (Planungssession 18./19.09.2026), bereit für den Umsetzungsplan
Löst ab: die nur lokal vorliegende Juni-Spec homeserver/docs/superpowers/specs/2026-06-14-paperless-ngx-v3-ollama-design.md
(v3-Beta gegen ollama-ipex auf dem NUC — überholt durch paperless-ngx 3.1 und den Entscheid, dass alles KI-seitige
auf den aiserver wandert). Pfadangaben wie paperless-ngx/… und infrastructure/… beziehen sich auf das Repo homeserver.
1. Kontext und Ziel¶
Paperless soll produktiv werden: Robins gesamter Papier- und Mailbestand wandert hinein, der Zulauf läuft über den
Netzwerk-Scanner und Proton Mail, die KI-Kette über llama-swap auf dem aiserver. Der heutige Stack (paperless-ngx:2.20,
ein Testdokument) war nur zum Ausprobieren da und wird komplett neu aufgesetzt, ohne Datenübernahme.
Nicht Ziel dieser Epic: Zugriff von außen, Lars' Konto, SSO, Dropbox-Spiegel, Restore-Probe (alles bewusst in E7b, siehe Abschnitt 12).
2. Entscheidungen¶
| Frage | Entscheidung | Quelle |
|---|---|---|
| Datenübernahme | Keine. Greenfield, alte Daten werden geleert | Robin 18.09. |
| Zugriff von außen | Keiner. Nur interner Traefik-Router | Robin 19.09. |
| Nutzerkreis | Zielbild: Robin und Lars mit getrennten Beständen. Jetzt nur Robins Konto; Lars in E8 oder E7b | Robin 19.09. |
| Gemeinsame Dokumente | Ohne Eigentümer (Paperless zeigt sie allen Konten = Robin und Lars), Speicherpfad gemeinsam/… neben robin/ und lars/. Bis Lars' Konto kommt: normal scannen, Tag Gemeinsam, später in einem Schritt umstellen. Kommt ein drittes Konto dazu → Gruppe „Haushalt" statt eigentümerlos. Ein ASN-Kreis für den Haushalt (zweite Etikettenrolle nur mit getrenntem Bereich) |
Robin 10.10. |
| Ablagelogik | Ordnerbaum über Speicherpfade je Lebensbereich, oberste Ebene = Eigentümer, _Unsortiert als Auffang |
Robin 19.09. |
| Steuer | Tag, kein Ordner. Ein Tag je Steuerjahr (Steuer 2024, Steuer 2025) mit gespeicherter Ansicht; ein Datumsfilter trifft das Steuerjahr nicht, weil die Belege erst im Folgejahr kommen |
Robin 19.09., 29.09. |
| Taxonomie | Startschema (Abschnitt 6), wächst im Betrieb; Korrespondenten darf die KI anlegen, Typen/Tags/Pfade nicht | Robin 19.09. |
| ASN | Barcode-Etiketten mit Präfix ASN auf jedem Papier, das behalten wird. ASN-Barcodes trennen zugleich den Stapel |
Robin 19.09. |
| Zulauf Papier | HP Color LaserJet Pro MFP 4302 (fdn/fdw, Duplex-Einzug) → neue SMB-Freigabe → Consume. /mnt/scanner bleibt unangetastet (überwiegend Lars' Dokumente) |
Robin 18./19.09. |
| Scan-Profil | Farbe, 300 dpi, beidseitig, PDF | Robin 19.09. |
| Zulauf Mail | Proton Mail Bridge headless im Stack, Proton-Label „Paperless" (kein Ordnerzwang), Robin hat Proton Unlimited | Robin 19.09. |
| KI-Kette | Native v3-KI über openai-like → llama-swap 10.10.10.7:9292. Vorschläge brain-llamacpp, Embeddings embed-llamacpp. Vision-OCR nur bei gerissener Schwelle (Abschnitt 7) |
Robin 19.09. |
| Speicherort | Bleibt: Dokumente auf /mnt/paperless (UNAS, NFS), DB/Index/Consume auf der SSD |
Robin 19.09. |
| Tika/Gotenberg | Bleiben (Mail-als-PDF, Office-Anhänge) | Robin 19.09. |
| Secrets | Infisical-Agent, Pfad /paperless-ngx; getrackte paperless.env wird gelöscht; neuer PAPERLESS_SECRET_KEY (#194) |
Roadmap |
| Exporter | Nächtlicher document_exporter in E7; die Restore-Probe daraus in E7b |
Robin 19.09. |
3. Architektur¶
Ein Compose-Stack paperless-ngx/ mit sechs Containern auf den bestehenden Netzen proxy_network (extern) und
paperlessngx_internal (bridge).
| Container | Image | Rolle |
|---|---|---|
paperless_ngx |
ghcr.io/paperless-ngx/paperless-ngx:3.1.x |
App, Consumer, KI-Client |
paperless_db |
docker.io/library/postgres:18.x |
Datenbank (SSD) |
paperless_redis |
docker.io/library/redis:8.x |
Broker/Cache (SSD) |
gotenberg |
docker.io/gotenberg/gotenberg:8.x |
Mail/Office → PDF |
tika |
docker.io/apache/tika:3.x |
Textextraktion Office/Mail |
protonmail-bridge |
Auswahl im Plan (Abschnitt 8) | IMAP-Brücke zu Proton, nur im internen Netz |
Genaue Patch-Versionen werden im Plan nachgeschlagen, nicht aus dem Kopf gesetzt.
Mounts:
| Host | Container | Zweck |
|---|---|---|
/mnt/ssd/container-data/paperless/data |
/usr/src/paperless/data |
Index, Klassifikator, LLM-Index |
/mnt/ssd/container-data/paperless/db |
Postgres-Datadir | Datenbank |
/mnt/ssd/container-data/paperless/redis |
/data |
Redis |
/mnt/ssd/container-data/paperless/consume |
/usr/src/paperless/consume |
Zulauf, Unterordner je Eigentümer |
/mnt/ssd/container-data/paperless/protonmail-bridge |
Bridge-Datenverzeichnis | Bridge-Vault und Mail-Cache |
/mnt/paperless/media |
/usr/src/paperless/media |
Originale, Archiv-PDFs, Thumbnails (UNAS) |
/mnt/paperless/export |
/usr/src/paperless/export |
Exporter-Ziel (UNAS) |
/mnt/paperless/trash |
/usr/src/paperless/trash |
Papierkorb (UNAS) |
Speicherort-Begründung: UNAS ist RAID6, beide Pfade stehen in beiden borgmatic-Ketten, der Mount-Guard aus #240
prüft /mnt/paperless, und Immich folgt demselben Muster. Die Alternative „alles auf die SSD" wäre operativ einfacher,
hinge aber bis zum nächsten Nachtlauf an einer einzelnen Platte. Datenbanken bleiben grundsätzlich auf der SSD.
Erreichbarkeit: https://paperless.home.robinwerner.net über Traefik, Router nur intern. PAPERLESS_TRUSTED_PROXIES
auf das Präfix 10.100. des Traefik-Netzes, sonst 403 beim Login (v3-Änderung an der Ratenbegrenzung). Präfix statt
CIDR, weil python-ipware die Liste per startswith vergleicht und 10.100.0.0/16 nie träfe.
4. Zulauf Papier¶
4.1 Samba-Freigabe auf dem NUC (nativ, kein Container)¶
Neue Freigabe neben der bestehenden [scanner]:
[paperless]
path = /mnt/ssd/container-data/paperless/consume/robin
valid users = scanner
force user = paperless
force group = paperless
create mask = 0660
directory mask = 0770
browseable = no
guest ok = no
writable = yes
Die include-Zeile dafür muss die letzte Zeile von [global] sein: Samba fügt die Datei wörtlich ein, und der
[paperless]-Header wechselt den Abschnitt für alles, was danach kommt (testparm warnt dann nur mit „Global
parameter … found in service section", die globalen Werte wären wirkungslos).
Dafür bekommt der NUC einen Systembenutzer paperless mit UID 977 / GID 988 — das ist die Identität, mit der der
Container läuft (USERMAP_UID/GID) und die auf dem UNAS-Export gilt. Beide IDs sind auf dem NUC noch unbelegt
(getent liefert nichts). Damit gehören gescannte Dateien von Anfang an dem Consumer, der sie nach dem Import löscht.
Zwei globale Korrekturen im selben Eingriff:
server min protocol = SMB2(heuteNT1, also SMB1; der 4302 braucht es nicht, HP schreibt SMB2/3 vor). Vorher prüfen, ob noch ein SMB1-Client existiert (smbstatus, Logs).map to guest = Never(heuteBad Password: ein falsches Passwort wird still zum Gastzugang).
[scanner] → /mnt/scanner bleibt unverändert. Alle Host-Schritte sind Robins Hand, per Runbook, mit testparm -s
vor dem Reload.
4.2 Quick Sets am HP 4302¶
| Quick Set | Netzwerkpfad | Einstellungen |
|---|---|---|
| Paperless | \\10.10.10.3\paperless |
PDF, Farbe, 300 dpi, beidseitig, Dateiname-Präfix scan |
| Ablage | \\10.10.10.3\scanner |
bestehend, unverändert |
Einrichtung im Embedded Web Server unter Settings → Control Panel Customization → Quick Sets, Benutzer scanner.
IP statt NetBIOS-Name, weil die Namensauflösung am Gerät die häufigste Fehlerquelle ist. Der Dateiname vom Gerät ist
egal, die KI setzt den Titel neu.
4.3 Stapel trennen über ASN¶
Trennung per Barcode und ASN-Barcode sind beide aktiv. Paperless beginnt dann an jeder Seite mit ASN-Etikett ein
neues Dokument und behält diese Seite (anders als bei PATCHT-Trennblättern, die verworfen werden). Ein Stapel mit
je einem Etikett auf Seite 1 wird also in einem Scanvorgang zu n Dokumenten mit je ihrer ASN. Eine schon vergebene ASN
lässt Paperless das Dokument ablehnen und protokollieren — doppelte Nummern fallen sofort auf.
PAPERLESS_CONSUMER_ENABLE_BARCODES: "true" # Trennung
PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE: "true" # ASN setzen + an ASN trennen
PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX: "ASN"
PAPERLESS_CONSUMER_BARCODE_MAX_PAGES: "0" # alle Seiten prüfen (Einzug: 50 Blatt)
# nur falls kleine Etiketten nicht erkannt werden (Probelauf):
# PAPERLESS_CONSUMER_BARCODE_DPI: "600"
# PAPERLESS_CONSUMER_BARCODE_UPSCALE: "1.5"
4.4 Consumer¶
PAPERLESS_CONSUMER_RECURSIVE: "true" # consume/<eigentümer>/
PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS: "false" # Änderung: Unterordner = Eigentümer, kein Tag
PAPERLESS_CONSUMER_DELETE_DUPLICATES: "true" # v3 ließe Duplikate sonst durch
PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED: "false" # Duplex kommt vom Einzug
Eigentümer und Inbox-Tag setzt Workflow W1 (Abschnitt 6.5) über den Pfadfilter */robin/*. Lars' Zweig ist später
ein zweiter Unterordner, eine zweite Freigabe und ein zweiter Workflow — kein Umbau.
Probelauf: ausschließlich frisch gescannte eigene Dokumente. /mnt/scanner wird weder verschoben noch kopiert.
5. Ordnerlogik und Dateinamen¶
Die Ordnerstruktur in media/documents/archive/ (und später im Dropbox-Spiegel) entsteht aus Speicherpfaden; die
globale PAPERLESS_FILENAME_FORMAT ist nur der Auffang, wenn kein Speicherpfad gesetzt ist.
robin/
Arbeit/<Korrespondent>/<Jahr>/<Datum> <Titel> ASN<Nummer>.pdf
Finanzen/…
Versicherungen/…
Wohnung/…
Gesundheit/…
Behörden/…
Studium & Zeugnisse/…
Fahrzeug/…
Verträge & Abos/…
_Unsortiert/<Korrespondent>/<Jahr>/…
Gemeinsamer Dateinamenteil aller Vorlagen (Jinja):
{{ owner_username }}/<Lebensbereich>/{{ correspondent }}/{{ created_year }}/{{ created }} {{ title }}{% if asn %} ASN{{ '%05d' | format(asn | int) }}{% endif %}
Auffang: PAPERLESS_FILENAME_FORMAT mit _Unsortiert als Lebensbereich. Der Unterstrich sortiert den Ordner nach
oben, Robin sieht sofort, was noch einzuordnen ist. Regeln:
- Paperless leitet Ordner aus Metadaten ab, nie umgekehrt. Zuordnung passiert in Paperless (Speicherpfad setzen), die Datei wandert automatisch. Dateien im Spiegel von Hand zu verschieben ist tabu.
- Die ASN im Dateinamen ist der Rückweg zum Papier.
- Die Nullauffüllung (
%05d) spiegelt die Etiketten (ASN00042). Paperless übergibtasnals Text, deshalb stehtasn | intvor demformat-Filter; ohne die Umwandlung wirft die Vorlage einenTypeError, Paperless fängt ihn still und legt die Datei als0000042.pdfim Wurzelverzeichnis ab (Befund des Abschlussreviews 20.09., in der Sandbox verifiziert). Der Fall ohne ASN bleibt durch{% if asn %}übersprungen.
6. Ablage-Startschema¶
Das Schema liegt als YAML unter paperless-ngx/seed/ im Repo. Ein uv run-Skript legt es über die REST-API
idempotent an (vorhandene Objekte werden nicht dupliziert). Damit ist die Struktur versioniert, reviewbar und beim
Neuaufbau reproduzierbar. Der API-Token kommt aus der Umgebung (PAPERLESS_TOKEN), nie aus dem Repo.
6.1 Dokumenttypen (feste Liste, KI legt keine an)¶
Rechnung · Vertrag · Bescheid · Schreiben · Zeugnis/Urkunde · Gehaltsabrechnung · Kontoauszug · Versicherungspolice · Kündigung · Beleg/Quittung · Antrag/Formular · Steuerbescheid · Bestellung/Auftragsbestätigung · Sonstiges
6.2 Speicherpfade (neun plus Auffang, KI legt keine an)¶
Arbeit · Finanzen · Versicherungen · Wohnung · Gesundheit · Behörden · Studium & Zeugnisse · Fahrzeug · Verträge & Abos
6.3 Tags (KI vergibt nur bestehende)¶
- Status:
Inbox(automatisch beim Import, Robin entfernt ihn beim Durchsehen) ·Handeln·Steuer·Dauerhaft(Urkunden, nie wegwerfen) ·E-Mail(Herkunft Mail) - Thema: nur, wo der Speicherpfad nicht reicht — Start mit
Gemeinsam(vormalsFamilie),Garantie; wächst im Betrieb
6.4 Korrespondenten¶
Startliste aus Robins bekannten Absendern — die Liste liefert Robin beim Seed, sie ist bewusst nicht Teil dieser Spec. Die KI darf neue anlegen, weil ein Absendername eine Tatsache ist. Auto-Matching lernt mit.
6.5 Workflows¶
| Nr. | Trigger | Aktionen |
|---|---|---|
| W1 | Verarbeitung gestartet, Pfadfilter */robin/* |
Eigentümer robin, Tag Inbox |
| W2 | Dokument hinzugefügt | KI-Vorschläge anwenden: Titel und Erstelldatum überschreiben; Korrespondent mit Anlegen fehlender; Dokumenttyp, Speicherpfad und Tags nur bestehende |
Mails brauchen keinen eigenen Workflow: Eigentümer und Tags setzt die Mail-Regel selbst (Abschnitt 8), W2 greift danach
wie bei Scans. Beim Entfernen von Inbox passiert nichts Automatisches — der Gang durch die Inbox ist Robins Kontrolle über die KI.
6.6 Gespeicherte Ansichten¶
Inbox · Handeln · Steuer laufendes Jahr · Unsortiert (kein Speicherpfad)
7. KI-Kette¶
7.1 Konfiguration¶
PAPERLESS_AI_ENABLED: "true"
PAPERLESS_AI_LLM_BACKEND: "openai-like"
PAPERLESS_AI_LLM_ENDPOINT: "http://10.10.10.7:9292/v1"
PAPERLESS_AI_LLM_MODEL: "brain-llamacpp" # qwen3.6 35B-A3B, 32k Kontext
PAPERLESS_AI_LLM_API_KEY: "none" # llama-swap hat keine Auth; Client verlangt trotzdem einen Wert
PAPERLESS_AI_LLM_CONTEXT_SIZE: "16384"
PAPERLESS_AI_LLM_REQUEST_TIMEOUT: "300" # Kaltstart von brain (Swap-Gruppe) + Generierung
PAPERLESS_AI_LLM_EMBEDDING_BACKEND: "openai-like"
PAPERLESS_AI_LLM_EMBEDDING_MODEL: "embed-llamacpp" # embeddinggemma 300m, resident, Kontext 2048
PAPERLESS_AI_LLM_EMBEDDING_CHUNK_SIZE: "1024"
PAPERLESS_LLM_INDEX_TASK_CRON: "30 3 * * *" # nach dem Borg-Lauf 02:04
PAPERLESS_AI_LLM_OUTPUT_LANGUAGE: "de-de" # Übersetzung = zweite LLM-Anfrage je Klassifikation
Geändert 22.09.: Ursprünglich sollte die Sprache der UI-Einstellung folgen; die ersten Scans bekamen englische Titel, die Benutzereinstellung wurde nicht übernommen. Fest gesetzt ist das Verhalten unabhängig vom Benutzer.
PAPERLESS_AI_LLM_ALLOW_INTERNAL_ENDPOINTS bleibt auf dem Default true (private Adresse erlaubt).
7.2 Was die KI leistet¶
Vorschläge für Titel, Tags, Korrespondent, Typ, Speicherpfad und Datum aus dem OCR-Text; automatisches Anwenden über W2; ähnliche Dokumente und Dokumenten-Chat über den Embedding-Index. Sie liest keine Bilder (OCR bleibt Tesseract) und setzt keine ASN (kommt vom Barcode). Der klassische lernende Klassifikator läuft parallel weiter.
Wie die KI die Taxonomie wählt (Befund 22.09., v3.1.3-Quelltext): Das Modell bekommt nicht die Liste der
Speicherpfade, Typen und Tags, sondern nur „Kandidaten aus ähnlichen Dokumenten", die Paperless aus dem Embedding-
Index holt. Ohne Kandidaten schlägt es freie Namen vor (englisch, dann übersetzt), die exakt oder unscharf gegen den
Bestand abgeglichen werden; Speicherpfade werden nie angelegt. Am ersten Tag ist der Index leer, alles landet in
_Unsortiert. Bootstrap: die ersten Dokumente von Hand einordnen; Kandidaten liest Paperless live aus der
Datenbank der ähnlichen Dokumente, die müssen nur im Index sein (nachts 03:30, sofort per document_llmindex
update). Danach bekommen ähnliche neue Dokumente Pfad, Typ und Tags als Kandidaten mit ID. Die Regel „nur Bestehendes" gilt weiter,
die Annahme „die KI wählt aus der festen Liste" war falsch. Kosten: je Aktion zwei Anfragen (Klassifikation +
Übersetzung), bei drei Aktionen in W2 sechs je Dokument; Messung in der Abnahme.
7.3 Modellentscheid per Mini-Turnier¶
Kandidat 1 ist brain-llamacpp (Qualität, 32k Kontext, swappt in der heavy-Gruppe). Kandidat 2 ist
json-llamacpp (granite 8B in der docs-Gruppe, kein Swap, 2 s je Dokument, Turnier-erprobt für JSON). Auf den ersten
Dokumenten werden beide über die Vorschlagsfunktion verglichen (Trefferquote je Feld, Latenz). Der Sieger bleibt in der
Compose-Datei, das Ergebnis geht ins Umsetzungs-Log.
Ergebnis 27.09. (fünf von Hand eingeordnete Dokumente, ai_duel.py): brain 3/5 Korrespondent, 4/5 Typ, 5/5
Pfad bei 60 s je Anfrage; coder 2/5, 4/5, 4/5 bei 14 s; translator 4/5, 4/5, 5/5 bei 56 s. Die 60 s waren
Denktext (13 KB Antwort gegen 1,5 KB bei coder). Neue Rolle paperless-llamacpp = brain-Gewichte mit
--reasoning off (aiserver#29, Gruppe docs): 3/5, 4/5, 4/5 bei 9 s. Damit ist sie das Paperless-Modell
(homeserver#252); sechs Anfragen je Dokument dauern rund 40 s statt drei Minuten, die drei Aktionen bleiben. json
schied als Kandidat aus (seit Testrunde 3 ein Bild-zu-Felder-Modell ohne Chat).
Bekannte Einschränkung: Paperless setzt embeddinggemmas Task-Präfixe nicht; die Trefferquote liegt etwas unter den 93 % R@5 aus dem Turnier.
7.4 Vision-OCR-Schwelle (Entscheid „Vision-OCR ja/nein")¶
Nach dem Probelauf (20 Dokumente) wird die OCR-Qualität geprüft: Beträge, Namen, IBANs, Aktenzeichen über die
Volltextsuche auffindbar? Sind mindestens 2 von 20 unbrauchbar, wird in E7b paperless-gpt nur für OCR
(paperless-gpt-ocr-auto, Vision-Modell ocr-llamacpp = german-ocr 3.1) ergänzt; Metadaten bleiben bei der
nativen KI, sonst kämpfen zwei Systeme um dieselben Felder. Unter der Schwelle bleibt es bei Tesseract.
8. Zulauf Mail (Proton)¶
Fakten: Proton bietet kein IMAP; die Brücke ist Proton Mail Bridge (bezahlter Plan nötig, Robin hat Unlimited).
Bridge zeigt jedes Proton-Label als IMAP-Ordner Labels/<Name>; die Mail bleibt dabei im Posteingang. Paperless'
Aktion „Custom Tag setzen" nutzt Gmails Label-Erweiterung, die Bridge nicht implementiert — also keine Rückmeldung per
Label. Paperless merkt sich verarbeitete Mails per UID (Mail → Processed Mails), doppelte Verarbeitung ist damit
unabhängig von der Aktion ausgeschlossen.
Design:
- Container
protonmail-bridgenur im Netzpaperlessngx_internal, keine veröffentlichten Ports, Daten unter/mnt/ssd/container-data/paperless/protonmail-bridge(in den Borg-Quellen). Läuft--noninteractive. - Image-Auswahl im Plan nach Kriterien: aus offiziellem Bridge-Quelltext gebaut, Release jünger als 6 Monate, amd64,
Healthcheck, kein
privileged. Kandidaten:ghcr.io/leakix/proton-bridge-docker,asyncura/proton-mail-bridge,Enucatl/docker-protonmail-bridge(mitcap_drop). - Einmalige Einrichtung durch Robin: Run-Container stoppen (Bridge hält einen Single-Instance-Lock unter
/data, das beide Container teilen), dannbridge --cliüber das Init-Profil, Login mit 2FA,infoliefert das Bridge-Passwort (nicht das Proton-Passwort), danach den Run-Container wieder starten. Das Bridge-Passwort landet nur im Paperless-Mailkonto (Paperless verschlüsselt es mit demSECRET_KEY), zusätzlich in Robins Passwortmanager. - In Proton: Label „Paperless". Robin setzt es von Hand oder per Proton-Filter (Sieve) nach Absender, z. B. alle Mails der Versicherer. Kein Ordnerzwang, die Mail bleibt im Posteingang.
- Paperless-Mailkonto: Host
protonmail-bridge, Port laut Image (143 oder 1143), Sicherheit keine — der Verkehr bleibt im Docker-internen Netz auf dem NUC, Bridge selbst spricht TLS zu Proton, und ein selbstsigniertes Bridge-Zertifikat würde am Client scheitern. - Mail-Regel: Ordner
Labels/Paperless, Anhangsfilter*.pdf, Umfang nur Anhänge (Start; „Mail als PDF" ist eine Betriebsentscheidung, Gotenberg ist dafür da), Titel aus Betreff, Korrespondent aus Absender, Eigentümerrobin, TagsInbox+E-Mail. Aktion nach Verarbeitung: Verschieben nachLabels/Paperless-erledigt. Korrigiert 23.09.: Eine Aktion „keine" existiert nicht (Auswahl: Löschen, Verschieben, Als gelesen markieren, Markieren, Tag), und die Aktion legt zugleich die Suchkriterien fest: „Als gelesen" holt nur ungelesene Mails (gelabelte Post ist meist gelesen), „Markieren" nur Mails ohne Stern (Robin nutzt Sterne), „Tag" braucht IMAP-Keywords, die Bridge nicht anbietet. „Verschieben" holt alle; und weil Bridge Labels als Ordner unterLabels/zeigt, tauscht das Verschieben zwischen zwei Labels nur das Label, die Mail bleibt im Posteingang. Maximales Alter0= unbegrenzt (Standard 30 Tage). - Abfrage alle 10 Minuten (Default
PAPERLESS_EMAIL_TASK_CRON).
Zu prüfen im Plan: Bridge synchronisiert den gesamten Postkasten lokal (verschlüsselter Cache). Die Größe von Robins Postfach bestimmt den Platzbedarf auf der SSD.
9. Secrets und Konfiguration¶
Infisical (EU, Projekt wie bei ollama/speedtest-tracker), Pfad /paperless-ngx, Env dev:
| Key | Zweck |
|---|---|
PAPERLESS_SECRET_KEY |
neu generiert (secrets.token_urlsafe(64)); der alte liegt im Git-Verlauf |
POSTGRES_PASSWORD |
Postgres-Cluster (greift nur bei leerem Datadir → Wipe ist Pflicht) |
PAPERLESS_DBPASS |
derselbe Wert für die App |
Agent-Template-Block in infrastructure/infisical-agent/agent.yaml.example und auf dem NUC in
/etc/infisical/agent.yaml; Compose bindet env_file: /run/infisical/paperless-ngx.env an paperless_ngx und
paperless_db. Der Superuser wird interaktiv angelegt (createsuperuser), das Passwort gehört in Robins
Passwortmanager, nicht nach Infisical. Der API-Token für das Seed-Skript wird nach dem ersten Login in der UI erzeugt
und Robin gibt ihn dem Skript per Umgebungsvariable.
Nicht-geheime Konfiguration wandert inline in docker-compose.yaml; paperless-ngx/paperless.env wird per
git rm entfernt (getrackter, geleakter SECRET_KEY, #194).
v3-Anpassungen gegenüber der 2.20-Konfiguration:
| Alt | Neu | Grund |
|---|---|---|
| — | PAPERLESS_DBENGINE=postgresql |
in v3 Pflicht |
PAPERLESS_OCR_MODE=skip |
PAPERLESS_OCR_MODE=auto |
skip entfernt |
PAPERLESS_OCR_SKIP_ARCHIVE_FILE=never |
PAPERLESS_ARCHIVE_FILE_GENERATION=always |
jedes Dokument bekommt ein Archiv-PDF — nur so ist documents/archive/ (Spiegelquelle in E7b) vollständig, auch bei born-digitalen PDFs |
PAPERLESS_DB_TIMEOUT=30 |
PAPERLESS_DB_OPTIONS=connect_timeout=30 |
konsolidiert |
PAPERLESS_CONSUMER_IGNORE_PATTERNS=[…] |
entfällt | v3-Defaults (Regex) decken .*, ._*, .DS_Store, Thumbs.db ab |
| — | PAPERLESS_TRUSTED_PROXIES=10.100. |
Login-403 hinter Traefik (Präfix-Match, kein CIDR) |
SUBDIRS_AS_TAGS=true |
false |
Unterordner = Eigentümer |
COLLATE_DOUBLE_SIDED=true |
false |
Duplex-Einzug |
PAPERLESS_TASK_WORKERS=4 |
2 |
der NUC teilt die CPU mit rund 60 Containern |
Unverändert: USERMAP_UID/GID 977/988, OCR_LANGUAGE=deu+eng, Deskew/Rotate/Clean, OCR_OUTPUT_TYPE=pdfa,
THREADS_PER_WORKER=2, TRASH_DIR, EMPTY_TRASH_DELAY=30, AUDIT_LOG_ENABLED, Session-Cookies, Postgres-Tuning.
10. Backup und Betrieb¶
- Borg-Quellen:
/mnt/ssd/container-data(DB, Index, Consume, Bridge) und/mnt/paperless(Media, Export, Trash) stehen bereits in beiden borgmatic-Ketten. Der DB-Dump greift automatisch (predeploy-backup.sherkennt Postgres-Container am Image, #241). Keine Backup-Änderung nötig — nur der Nachweis nach dem ersten Nachtlauf. - Exporter-Timer
paperless-export.timer, täglich 01:15 (vor Borg 02:04), versioniert unterpaperless-ngx/host-config/:docker exec -T paperless_ngx document_exporter ../export --delete --use-folder-prefix --split-manifest --no-progress-bar. Der Export ist Paperless' eigenes Sicherungsformat: alle Originale und Archiv-PDFs mit lesbaren Namen plusmanifest.jsonmit dem kompletten Datenbankinhalt (Tags, Korrespondenten, Typen, Pfade, ASN, Notizen, Workflows, Mail-Regeln, Rechte).document_importerliest ihn in eine leere Instanz zurück, unabhängig von Postgres-Version und Pfaden. Inkrementell; Kosten einmal die Dokumentgröße auf der UNAS. - Überwachung:
- Uptime-Kuma-Monitor (VPS) auf
https://paperless.home.robinwerner.net/— Kuma erreicht interne Domains. - Consume-Stau-Prüfung: Timer alle 15 min schreibt
paperless_consume_stale_files(Dateien älter als 30 min unterconsume/) in den node-exporter-Textfile-Collector; Prometheus-Regel feuert bei> 0für 30 min. Die Unit läuft ohne Capabilities, aber mitSupplementaryGroups=paperless, weil der Consume-Baum0770ist. Genau dieses stille Versagen blieb mit Syncthing neun Monate unbemerkt. Nach dem Deploy prüfen, dass die Metrik Serien hat (E3-Prinzip). - Deploy-Reihenfolge (NUC, Robins Hand): Infisical-Secrets + Agent-Template → Samba (Benutzer, Freigabe, SMB2) →
alten Stack
down→ Datenverzeichnisse leeren (Sicherheitsblick vorher: genau ein Dokument) →git pullals root →docker compose config→up -d→ Superuser → Seed → Quick Sets → Bridge-Login → Mailkonto/-regel → Timer.
11. Abnahme E7¶
- 20 echte Dokumente über den Scanner (Quick Set Paperless), Stapel mit ASN-Etiketten in einem Durchgang:
Trennung stimmt, jede ASN gesetzt, mindestens 15 ohne Handkorrektur richtig in Korrespondent, Typ und
Speicherpfad. Gilt für den zweiten Stapel: Der erste wird von Hand eingeordnet und der Index neu gebaut, erst
dann hat die KI Kandidaten (Abschnitt 7.2). Und auf der Platte:
media/documents/archive/robin/…zeigt den Ordnerbaum aus Abschnitt 5, keine Datei liegt als0000042.pdfim Wurzelverzeichnis (der stille Rückfall, wenn eine Vorlage nicht rendert). - Eine Mail mit PDF-Anhang mit Label „Paperless" landet ohne Zutun in der Inbox, Eigentümer Robin, Tag
E-Mail. - Export liegt im Nachtarchiv:
borgmatic list --archive latest --path mnt/paperless/exportzeigt Manifest und Dokumente (nicht--find, das liefert falsche Nullen). - Volltextsuche findet einen Betrag und eine Aktennummer aus einem Scan (OCR-Nachweis, Grundlage für 7.4).
- Dokumenten-Chat beantwortet eine Frage zu einem Dokument mit Quellenlink (Index-Lauf erfolgt).
- Consume-Stau-Metrik hat Serien, Kuma-Monitor grün.
12. Bewusst in E7b¶
- Dropbox-Spiegel (#242):
rclone syncvonarchive/robin/nachDokumente/Paperless,--max-deleteund--backup-dirals Löschschutz, eigener Timer. Klartext (Robins Entscheid), Ordner ist ein Spiegel, kein Ablageort. - Restore-Probe: Export aus dem Borg-Archiv holen, auf dem Laptop in eine Wegwerf-Instanz importieren, ein Dokument mit Tags und ASN öffnen. Bis dahin gilt ehrlich: Dateien belegt, Rückweg ungeprüft.
- Lars' Konto und Eigentümertrennung (zweiter Consume-Zweig, Freigabe, Workflow), SSO über Authelia (E8; läuft auf dem VPS, OIDC-Clients fehlen noch).
- Vision-OCR über paperless-gpt, nur wenn die Schwelle aus 7.4 reißt.
- „Mail als PDF" in der Mail-Regel, Custom Fields (Betrag, Fälligkeit), weitere Themen-Tags — nach Betriebserfahrung.
13. Prüfpunkte für den Umsetzungsplan¶
- Aktuelle Patch-Tags für paperless-ngx 3.1, Postgres 18, Redis 8, Gotenberg 8, Tika 3 nachschlagen.
- Bridge-Image nach den Kriterien aus Abschnitt 8 wählen; Datenpfad und IMAP-Port des gewählten Images.
- ~~
format-Filter im Dateinamen-Jinja~~ — geklärt 20.09.: Filter vorhanden,asnkommt als Text,asn | intlöst es (Abschnitt 5). - Barcode-Erkennung an Robins realen Etiketten (DPI/Upscale).
- SMB1-Clients vor
server min protocol = SMB2. - ~~Format von
PAPERLESS_AI_LLM_OUTPUT_LANGUAGE~~ — geklärt 22.09.: Sprachcode aus DjangosLANGUAGES, für Deutschde-de; gesetzt, weil die UI-Sprache nicht reichte. - Größe von Robins Proton-Postfach (Bridge-Cache auf der SSD).
- Nach dem ersten Nachtlauf: DB-Dump und Export im Archiv belegen.
14. Quellen¶
- Issue #190 (Agenda-Kommentar 18.09.), #87, #242, #240/#241
- paperless-ngx 3.1.3:
docs/configuration.md(AI, Barcodes, Consumer),docs/migration-v3.md,docs/usage.md(Workflows → Apply AI Suggestions, Incoming Email, Processed Mail),docs/advanced_usage.md(AI features, Document Splitting / ASN),docs/administration.md(Exporter) - HP Support: Set up Scan to Network Folder (Quick Sets, EWS), User Guide 4301/4302
- Proton: Labels in Bridge; paperless-ngx Discussion #12133 (Custom Tag vs. Bridge)
- paperless-gpt README (OCR-Provider,
PDF_UPLOAD, Tag-Steuerung) - aiserver:
llama-swap/config.yaml,docs/testrunde-2/(Turniere OCR/JSON/Embeddings) - NUC (lesend, 18./19.09.):
smb.conf,/mnt/paperless-Mount, Container-Datenverzeichnis, Infisical-Agent