Paperless-ngx auf RKE2 (Helm Chart)

Bereitstellung von Paperless-ngx auf einem RKE2 Kubernetes-Cluster als maßgeschneiderter Helm Chart.

Alle Parameter (Domain, Storage, Ingress, OpenBao/ESO, CloudNative-PG, Redis) sind zentral an einem Ort in values.yaml gebündelt.


🏗 Architektur

graph TD
    Client[Browser / Mobile App] -->|HTTPS| Ingress[Traefik Ingress Controller]
    Ingress -->|ClusterIP:8000| PaperlessSvc[Service: paperless]

    subgraph Namespace: paperless
        PaperlessSvc --> PaperlessPod[Pod: paperless]

        PaperlessPod -->|Redis Queue| RedisPod[Pod: paperless-redis]
        PaperlessPod -->|PostgreSQL Port 5432| CNPGCluster[(CloudNative-PG Cluster)]

        ESO[External Secrets Operator] -->|Sync from OpenBao| K8sSecret[Secret: paperless-secrets]
        K8sSecret -.->|PAPERLESS_SECRET_KEY, Admin| PaperlessPod
        CNPGSecret[Secret: paperless-postgres-app] -.->|DB Credentials| PaperlessPod

        PaperlessPod --- PVCData[(PVC: paperless-data - Blockstorage / iSCSI)]
        PaperlessPod --- PVCMedia[(PVC: paperless-media - NFS)]
        PaperlessPod --- PVCConsume[(PVC: paperless-consume - NFS)]
        PaperlessPod --- PVCExport[(PVC: paperless-export - NFS)]
    end

📋 Voraussetzungen

Auf deinem RKE2-Cluster sollten folgende Komponenten aktiv sein:

  1. Ingress Controller: Traefik (RKE2 Standard)
  2. cert-manager: Für automatisches Ausstellen von TLS-Zertifikaten (mit cloudflare-cluster-issuer)
  3. CloudNative-PG Operator: Für PostgreSQL (postgresql.cnpg.io)
  4. External Secrets Operator (ESO): Mit ClusterSecretStore (z. B. openbao-secretstore)
  5. StorageClasses:
    • synology-csi-iscsi-retain (oder anderer Blockstorage für data / Suchindex)
    • nfs-retain (für media, consume, export)

📂 Chart-Struktur

.
├── Chart.yaml                  # Helm Chart Metadaten
├── values.yaml                 # ZENTRALE Konfiguration aller Variablen
├── templates/
│   ├── _helpers.tpl            # Helm Naming- und Label-Templates
│   ├── deployment.yaml         # Paperless-ngx Webserver & Worker
│   ├── service.yaml            # ClusterIP Service
│   ├── ingress.yaml            # Traefik Ingress mit cert-manager
│   ├── pvcs.yaml               # NFS PersistentVolumeClaims
│   ├── external-secret.yaml    # ESO ExternalSecret für OpenBao
│   ├── cnpg-cluster.yaml       # CloudNative-PG PostgreSQL Cluster
│   └── redis.yaml              # Redis 8 Alpine Broker
├── .gitea/
│   └── workflows/
│       └── lint.yaml           # Gitea Actions CI (YAML, Renovate & Helm Lint)
├── .yamllint.yaml              # YAML-Linter Konfiguration
└── renovate.json               # Renovate Bot Konfiguration (inkl. values.yaml)

⚙️ Zentrale Konfiguration (values.yaml)

Alle Einstellungen sind in values.yaml vorkonfiguriert:

  • Ingress: paperless.mig.hnrx.net (Traefik, TLS via cloudflare-cluster-issuer, proxy-body-size: 100m)
  • Storage: storageClass: nfs-retain, accessMode: ReadWriteMany (Data: synology-csi-iscsi-retain)
  • Secrets (ESO): ClusterSecretStore: openbao-secretstore, Pfad: paperless-ngx
  • Datenbank: CloudNative-PG mit ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie
  • Redis: docker.io/library/redis:8-alpine

📄 Scanner-Ordner (Synology NAS) als Consume-Volume einbinden

Liegt der Scan-Zielordner auf der Synology (z. B. via SMB vom Scanner befüllt), kann derselbe Ordner parallel via NFS in Kubernetes eingehängt werden:

persistence:
  consume:
    # Direkter NFS-Mount ohne extra PVC
    nfs:
      server: "192.168.1.10"
      path: "/volume1/scanner"

Wichtig auf der Synology (DSM):

  1. In der Systemsteuerung unter Gemeinsamer Ordner -> NFS-Berechtigungen für die IPs der RKE2-Nodes Lesen/Schreiben erlauben.
  2. Squash auf Alle Benutzer zu Admin zuordnen (oder Keine Zuordnung) stellen, damit Paperless importierte Dokumente nach dem Scannen löschen darf.

🔐 Secrets in OpenBao / Vault einrichten

Der ExternalSecret liest aus paperless-ngx:

Secret Key in OpenBao Ziel-Key im Secret Beschreibung
secret-key PAPERLESS_SECRET_KEY Zufälliger Secret-Key für Django-Sessions
admin-user PAPERLESS_ADMIN_USER (Optional) Initialer Admin-Benutzer
admin-password PAPERLESS_ADMIN_PASSWORD (Optional) Initiales Admin-Passwort
oidc-client-id OIDC_CLIENT_ID OAuth2 Client-ID aus Authentik
oidc-client-secret OIDC_CLIENT_SECRET OAuth2 Client-Secret aus Authentik

Datenbank-Passwort: Wird automatisch von CloudNative-PG generiert und im Secret paperless-postgres-app bereitgestellt.


🔑 OIDC / Authentik Einrichtung

In Authentik richtest du Paperless-ngx folgendermaßen ein:

  1. Provider anlegen:

    • Typ: OAuth2/OpenID Provider
    • Name: Paperless-ngx
    • Client type: Confidential
    • Redirect URI / Callback URL:
      https://paperless.mig.hnrx.net/accounts/oidc/authentik/login/callback/
      
    • Scopes: openid, email, profile, groups (im Authentik Provider unter Selected property mappings authentik default OAuth2/OIDC - Scope 'groups' zuweisen)
  2. Application anlegen:

    • Name: Paperless
    • Slug: paperless (ergibt die Provider-URL: https://<authentik-domain>/application/o/paperless/)
    • Provider: Den zuvor angelegten Provider auswählen
  3. Zugangsdaten in OpenBao hinterlegen:

    • Trage die Client ID und das Client Secret in OpenBao unter paperless-ngx als oidc-client-id und oidc-client-secret ein.
  4. Konfiguration in values.yaml:

    • oidc.enabled: true
    • oidc.serverUrl: z. B. https://authentik.mig.hnrx.net/application/o/paperless/
    • oidc.syncGroups: true
    • oidc.groupsClaim: "groups"
    • oidc.superuserGroup: "paperless-admins"
    • oidc.scopes: ["openid", "profile", "email", "groups"]
    • oidc.pkceEnabled: true
    • oidc.fetchUserinfo: true

Wichtig für Gruppen-Sync in Paperless: Gruppen müssen in Paperless-ngx mit exakt dem gleichen Namen angelegt sein, damit Mitglieder beim OIDC-Login automatisch zugeordnet werden (außer Superuser, welche über PAPERLESS_SOCIAL_ACCOUNT_SYNC_SUPERUSER_GROUP direkt Admin-Rechte erhalten).


📦 Release in die Gitea Helm Registry

Sobald ein Git-Tag gepusht wird (z. B. v0.1.0), führt die Pipeline den release-Job aus, baut das Helm-Chart-Paket und lädt es automatisch in die Gitea Package Registry hoch:

# Tag erstellen und pushen
git tag v0.1.0
git push origin v0.1.0

Chart aus der Gitea Registry verwenden

Nach dem Release kann das Chart direkt über Gitea bezogen werden (auch ideal für ArgoCD):

# Gitea Helm-Repository hinzufügen
helm repo add k8s https://git.hnrx.net/api/packages/k8s/helm

# Charts aktualisieren
helm repo update

# Installieren
helm upgrade --install paperless k8s/paperless-ngx \
  --namespace paperless \
  --create-namespace

🚀 Lokales Deployment via Helm

1. Trockenlauf (Manifeste lokal rendern & prüfen)

helm template paperless . -n paperless

2. Direkt aus dem lokalen Verzeichnis installieren

helm upgrade --install paperless . \
  --namespace paperless \
  --create-namespace

3. Status überprüfen

# Pods prüfen
kubectl get pods -n paperless -w

# CloudNative-PG Cluster
kubectl get cluster -n paperless

# ExternalSecret Status
kubectl get externalsecret -n paperless

# Ingress & Zertifikat
kubectl get ingress,certificate -n paperless

🛠 Nützliche Befehle

Superuser manuell anlegen (falls nicht über OpenBao gesetzt)

kubectl exec -it deployment/paperless -n paperless -c paperless -- python3 manage.py createsuperuser

Dokumente manuell importieren (Document Exporter / Importer)

# Export
kubectl exec -it deployment/paperless -n paperless -c paperless -- python3 manage.py document_exporter ../export

# Import
kubectl exec -it deployment/paperless -n paperless -c paperless -- python3 manage.py document_importer ../consume
S
Description
No description provided
Readme
194 KiB
0 Stars 0 Watchers 0 Forks
Languages
Go Template 100%