Co zrobione: - Nextcloud host = PIHA (always-on dla aktywnego uzycia), owner_node + LAN_BIND_IP/TRUSTED_PROXIES w .env, README zaktualizowane - Redis brokera Paperlessa: requirepass, PAPERLESS_REDIS_PASSWORD w .env po obu stronach (PIHA + worker@SOLARIA), healthchecki z auth - Domeny potwierdzone: paper.kapala.org, cloud.kapala.org (Cloudflare DNS-only -> Tailscale PIHA, wildcard cert juz pokrywa) — udokumentowane, nic nie utworzone - Backup Paperlessa zatwierdzony: document_exporter + rsync/borg -> SOLARIA, retencja 7/4/6, offsite jako future-note - Nextcloud pin: 34-apache (zweryfikowany aktualny stable, endoflife.date) - Whoosh fallback-worker: zaakceptowane bez zmian - Porty/wylaczenie local login/sizing OCR-workera: przeniesione z "decyzji" na "TODO przy deployu" - DECYZJE-do-podjecia.md zaktualizowane: wszystko poza portami/loginem/ sizingiem przeniesione do "Rozstrzygniete" Tylko edycja configow w repo — nic nie zdeployowane, zadne kontenery nie byly ruszane, DNS/vhosty nie utworzone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.4 KiB
Paperless-ngx (serwis, PIHA)
Serwis dokumentów filaru KB #2 (moduł 2, docs/kb/modules/02-paperless-service.md):
UI + API + Postgres + Redis. Always-on na PIHA. Ciężki OCR wykonuje osobny worker
na SOLARIA (services/paperless-worker/, moduł 3) — tu zostaje tylko wolny
fallback (1 worker × 1 wątek).
Paperless = archiwum REFERENCJA w hybrydzie kb-02 — jego storage jest źródłem prawdy dla KB. Backup jest OBOWIĄZKOWY (patrz niżej), nie opcjonalny.
Stack
| Kontener | Obraz | Rola |
|---|---|---|
paperless |
ghcr.io/paperless-ngx/paperless-ngx:2.14 |
UI+API+consumer+fallback-OCR (port 8000) |
paperless-db |
postgres:16-alpine |
metadane (alias db) |
paperless-broker |
redis:7-alpine (AOF on) |
kolejka zadań OCR (alias broker) |
Wszystkie porty bindowane na LAN_BIND_IP (192.168.31.5), nigdy 0.0.0.0:
8210→ web UI (za npm@PIHA, vhostpaper.kapala.org, LAN/Tailscale only)5434→ Postgres dla workera@SOLARIA (5433 zajęte przez kb-postgres); auth scram6380→ Redis dla workera@SOLARIA (6379 zajęte przez agent-system-redis);requirepassustawione —PAPERLESS_REDIS_PASSWORDw.envpo obu stronach
Obraz jest multi-arch (arm64 natywnie na Pi 5). Tag 2.14 MUSI być identyczny
z services/paperless-worker/docker-compose.yml — podbijać oba naraz.
Split OCR: serwis@PIHA + worker@SOLARIA (wynik badania)
Rozproszony worker nie jest oficjalnie wspierany przez Paperless-ngx, ale
jest wykonalny i potwierdzony przez maintainerów (GH discussion #3900): drugi
host odpala ten sam obraz z command: celery --app paperless worker i musi
widzieć ten sam Redis, tego samego Postgresa i te same pliki. Stąd:
- storage dokumentów leży na PIHA (bind mounty
/opt/homelab/data/paperless/*) i jest eksportowany przez NFS po LAN (nie Tailscale) do SOLARII; - ścieżki w kontenerze (
/usr/src/paperless/{data,media,consume}) muszą być identyczne po obu stronach — payloady zadań i DB niosą ścieżki absolutne; - pliki mają właściciela numerycznego UID 1000 (
USERMAP_UID/GID=1000po obu stronach) — NFS przenosi numeryczne ID, nie nazwy; - wbudowany worker na PIHA (nie da się go wyłączyć w stockowym obrazie) działa jako wolny fallback, gdy SOLARIA śpi; zadania czekają w Redis (AOF włączone, restart brokera nie gubi kolejki).
Szczegóły NFS (export na PIHA, mount na SOLARIA, ryzyko indeksu Whoosh) —
services/paperless-worker/README.md.
OIDC przez Forgejo
Mechanizm: django-allauth z providerem openid_connect
(PAPERLESS_APPS=allauth.socialaccount.providers.openid_connect), konfiguracja
providera w JSON-ie PAPERLESS_SOCIALACCOUNT_PROVIDERS (w .env, bo zawiera
client secret — patrz env.example).
Rejestracja w Forgejo (Settings → Applications, wzorzec jak Vikunja):
- Redirect URI:
https://paper.kapala.org/accounts/oidc/forgejo/login/callback/ - Confidential client; scope
openid profile email
forgejo.kapala.org jest przypięte przez extra_hosts do 192.168.31.5
(npm na PIHA), żeby OIDC discovery szło po LAN — ta sama lekcja co w Vikunji.
Lokalny login zostaje na czas bootstrapu (konto PAPERLESS_ADMIN_USER);
po zweryfikowaniu OIDC ustawić PAPERLESS_DISABLE_REGULAR_LOGIN=true +
PAPERLESS_REDIRECT_LOGIN_TO_SSO=true (decyzja podjęta — zrobić PRZY DEPLOYU,
po potwierdzeniu logowania OIDC; TODO w compose).
Storage i backup (WARUNEK BRZEGOWY hybrydy)
Dane na PIHA NVMe:
/opt/homelab/data/paperless/media— oryginały + zarchiwizowane PDF-y, niezastępowalne/opt/homelab/data/paperless/data— indeks wyszukiwania (Whoosh) + klasyfikator — odtwarzalne (document_index reindex)/opt/homelab/data/paperless/consume— katalog zrzutu do ingestupaperless_pgdata(named volume) — metadane (tagi, korespondenci, daty)paperless_redisdata(named volume) — AOF kolejki zadań
Backup (zatwierdzone — cel: SOLARIA, LAN; offsite później)
- Warstwa 1 — eksport spójny: nocny cron na PIHA:
docker exec paperless document_exporter ../export --delete -z— wbudowane narzędzie; zrzuca oryginały + archiwa +manifest.json(pełne metadane, odtwarzalne przezdocument_importerbez dumpa SQL). Ląduje w/opt/homelab/data/paperless/export. - Warstwa 2 — kopia poza hosta: rsync/borg eksportu na SOLARIA (2 TB NVMe, ta sama LAN) — SOLARIA sesyjna, więc pull przy starcie lub push z retry. Wystarcza na start; VPS odpada (brak miejsca).
- Retencja (zatwierdzona): 7 dziennych + 4 tygodniowe + 6 miesięcznych.
- Dump Postgresa nie jest konieczny do odtworzenia (manifest wystarcza),
ale tani — można dołożyć
pg_dumpdo tej samej nocnej pętli. - Future-note (poza zakresem tego etapu): offsite backup (np. restic → chmura) poza SOLARIA-LAN, gdy pojawi się potrzeba/budżet.
Ten etap to tylko config + dokumentacja decyzji — cron/skrypt deployowy (cron entry na PIHA, rsync/borg do SOLARII) powstaje przy deployu modułu 2, nie tutaj.
RAM na PIHA
Oczekiwany spoczynek: paperless ~400–600 Mi (gunicorn + consumer + beat +
1 worker), postgres ~80 Mi, redis ~15 Mi. Limity twarde w
hosts/piha/runtime/paperless/docker-compose.override.yml. Warunek: moduł 0
(odchudzenie PIHA) wykonany — po nim ~3.8 Gi available.
Cutover checklist (przy deployu — NIE teraz)
- Moduł 0 (piha-slim) domknięty;
free -gna PIHA potwierdza zapas. - Porty wolne na żywym hoście:
ss -tlnp | grep -E '8210|5434|6380'. mkdir -p /opt/homelab/data/paperless/{data,media,consume,export}na PIHA..envzenv.example(sekrety + rejestracja OAuth2 w Forgejo).- DNS: rekord A
paper.kapala.orgw Cloudflare →100.108.208.3(Tailscale PIHA, DNS Only) — ten sam wzorzec coha.kapala.org/immich.kapala.org(docs/sessions/2026-06-30-kapala-cloudflare-wildcard-mesh.md); wildcard*.kapala.orgjuż pokrywa tę subdomenę, nowy cert niepotrzebny. Plus vhost w npm@PIHA (HTTPS →192.168.31.5:8210, Advanced puste). docker compose up -d+./healthcheck.sh+ testowy login OIDC.- Export NFS dla workera (patrz
services/paperless-worker/README.md) — dopiero przy module 3. - Wpis w
hosts/piha/services.yaml(dopiero przy deployu — wcześniej supervisor widziałby drift dla nieistniejącego serwisu).