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:
- Ingress Controller: Traefik (RKE2 Standard)
- cert-manager: Für automatisches Ausstellen von TLS-Zertifikaten (mit
cloudflare-cluster-issuer) - CloudNative-PG Operator: Für PostgreSQL (
postgresql.cnpg.io) - External Secrets Operator (ESO): Mit
ClusterSecretStore(z. B.openbao-secretstore) - StorageClasses:
synology-csi-iscsi-retain(oder anderer Blockstorage fürdata/ Suchindex)nfs-retain(fürmedia,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 viacloudflare-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):
- In der Systemsteuerung unter Gemeinsamer Ordner -> NFS-Berechtigungen für die IPs der RKE2-Nodes
Lesen/Schreibenerlauben.- Squash auf
Alle Benutzer zu Admin zuordnen(oderKeine 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-appbereitgestellt.
🔑 OIDC / Authentik Einrichtung
In Authentik richtest du Paperless-ngx folgendermaßen ein:
-
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 mappingsauthentik default OAuth2/OIDC - Scope 'groups'zuweisen)
-
Application anlegen:
- Name:
Paperless - Slug:
paperless(ergibt die Provider-URL:https://<authentik-domain>/application/o/paperless/) - Provider: Den zuvor angelegten Provider auswählen
- Name:
-
Zugangsdaten in OpenBao hinterlegen:
- Trage die
Client IDund dasClient Secretin OpenBao unterpaperless-ngxalsoidc-client-idundoidc-client-secretein.
- Trage die
-
Konfiguration in
values.yaml:oidc.enabled: trueoidc.serverUrl: z. B.https://authentik.mig.hnrx.net/application/o/paperless/oidc.syncGroups: trueoidc.groupsClaim: "groups"oidc.superuserGroup: "paperless-admins"oidc.scopes:["openid", "profile", "email", "groups"]oidc.pkceEnabled: trueoidc.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_GROUPdirekt 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