# Single container runs webserver + consumer + scheduler (paperless-ngx's # stock entrypoint does this internally) - no need to split into separate # Deployments. replicas: 1 only: paperless-media is ReadWriteOnce, and the # consumer polling the media dir doesn't benefit from horizontal scaling here. # # Pinned to talos-cp-3: paperless-media's disk physically lives there. Longhorn # RWO volumes can only be attached from one node at a time, and the nightly # backup-cronjob.yaml also mounts this same PVC (read-only) to mirror it into # MinIO - pinning both to the same node avoids a cross-node attach conflict, # and keeps the 3.5Ti read/write path off the network entirely. apiVersion: apps/v1 kind: Deployment metadata: name: paperless spec: replicas: 1 strategy: type: Recreate # ReadWriteOnce media PVC - avoid two pods fighting over it selector: matchLabels: app: paperless template: metadata: labels: app: paperless spec: # Kubernetes injects legacy Docker-links env vars for every Service in # this namespace (_SERVICE_HOST, _PORT, ...). The Service here # is named "paperless", so that becomes PAPERLESS_PORT=tcp://:8000 - # paperless-ngx's own entrypoint reads PAPERLESS_PORT for gunicorn's # bind address, collides, and gunicorn crash-loops on "not a valid port # number". Disable the injection instead of renaming the Service. enableServiceLinks: false nodeSelector: kubernetes.io/hostname: talos-cp-3 containers: - name: paperless image: ghcr.io/paperless-ngx/paperless-ngx:2.20.15 ports: - containerPort: 8000 envFrom: - configMapRef: name: paperless-config env: - name: PAPERLESS_DBUSER valueFrom: secretKeyRef: name: paperless-db-app key: username - name: PAPERLESS_DBPASS valueFrom: secretKeyRef: name: paperless-db-app key: password - name: PAPERLESS_SECRET_KEY valueFrom: secretKeyRef: name: paperless-secrets key: PAPERLESS_SECRET_KEY - name: PAPERLESS_ADMIN_USER valueFrom: secretKeyRef: name: paperless-secrets key: PAPERLESS_ADMIN_USER - name: PAPERLESS_ADMIN_PASSWORD valueFrom: secretKeyRef: name: paperless-secrets key: PAPERLESS_ADMIN_PASSWORD - name: PAPERLESS_SOCIALACCOUNT_PROVIDERS valueFrom: secretKeyRef: name: paperless-oidc key: SOCIALACCOUNT_PROVIDERS_JSON resources: requests: { cpu: "500m", memory: "1Gi" } limits: { cpu: "2", memory: "4Gi" } volumeMounts: - name: media mountPath: /usr/src/paperless/media - name: data mountPath: /usr/src/paperless/data - name: consume mountPath: /usr/src/paperless/consume # Overrides paperless-ngx's own adapter.py in place - settings.py # hardcodes the import path, so no Django setting changes, just # the file content underneath it (see adapter-configmap.yaml). - name: adapter mountPath: /usr/src/paperless/src/paperless/adapter.py subPath: adapter.py readOnly: true volumes: - name: media persistentVolumeClaim: claimName: paperless-media - name: data persistentVolumeClaim: claimName: paperless-data - name: consume emptyDir: {} - name: adapter configMap: name: paperless-adapter