Files
paperless-ngx-deployment/app.yaml
T
feedc0de fbafa72cba
Test and deploy / test (push) Successful in 11s
Test and deploy / deploy (push) Failing after 17s
Add authenticated scanner UI and Paperless handoff
2026-10-04 19:17:01 +02:00

263 lines
8.2 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: valkey
namespace: paperless-ngx
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels: {app: valkey}
template:
metadata:
labels: {app: valkey}
spec:
automountServiceAccountToken: false
containers:
- name: valkey
image: valkey/valkey:9.0.6
args: ["--save", "", "--appendonly", "no"]
ports: [{name: redis, containerPort: 6379}]
readinessProbe:
exec: {command: [valkey-cli, ping]}
periodSeconds: 5
livenessProbe:
exec: {command: [valkey-cli, ping]}
periodSeconds: 20
resources:
requests: {cpu: 25m, memory: 64Mi}
limits: {memory: 256Mi}
---
apiVersion: v1
kind: Service
metadata:
name: valkey
namespace: paperless-ngx
spec:
selector: {app: valkey}
ports: [{name: redis, port: 6379, targetPort: redis}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless
namespace: paperless-ngx
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels: {app: paperless}
template:
metadata:
labels: {app: paperless}
spec:
automountServiceAccountToken: false
enableServiceLinks: false
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [arschrock]
containers:
- name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:3.2.1
ports: [{name: http, containerPort: 8000}]
env:
- {name: PAPERLESS_URL, value: "https://paper.brunner.ninja"}
- {name: PAPERLESS_REDIS, value: "redis://valkey:6379"}
- {name: PAPERLESS_TIME_ZONE, value: "Europe/Vienna"}
- {name: PAPERLESS_OCR_LANGUAGE, value: "deu+eng"}
- {name: PAPERLESS_THREADS_PER_WORKER, value: "4"}
- {name: PAPERLESS_CONSUMER_POLLING_INTERVAL, value: "30"}
- {name: PAPERLESS_APPS, value: "allauth.socialaccount.providers.openid_connect"}
- {name: PAPERLESS_SOCIAL_AUTO_SIGNUP, value: "true"}
- {name: PAPERLESS_SOCIAL_ACCOUNT_SYNC_GROUPS, value: "true"}
- {name: PAPERLESS_SOCIAL_ACCOUNT_SYNC_SUPERUSER_GROUP, value: "Paperless Admins"}
- name: PAPERLESS_SOCIALACCOUNT_PROVIDERS
valueFrom:
secretKeyRef: {name: paperless-oidc, key: providers}
- name: PAPERLESS_SECRET_KEY
valueFrom:
secretKeyRef: {name: paperless-secret-key, key: secret-key}
volumeMounts:
- {name: data, mountPath: /usr/src/paperless/data, subPath: data}
- {name: data, mountPath: /usr/src/paperless/media, subPath: media}
- {name: data, mountPath: /usr/src/paperless/consume, subPath: consume}
- {name: data, mountPath: /usr/src/paperless/export, subPath: export}
startupProbe:
httpGet: {path: /, port: http}
periodSeconds: 10
failureThreshold: 60
readinessProbe:
httpGet: {path: /, port: http}
periodSeconds: 10
livenessProbe:
httpGet: {path: /, port: http}
periodSeconds: 30
resources:
requests: {cpu: 100m, memory: 1Gi}
limits: {memory: 4Gi}
volumes:
- name: data
persistentVolumeClaim: {claimName: paperless-data}
---
apiVersion: v1
kind: Service
metadata:
name: paperless
namespace: paperless-ngx
spec:
selector: {app: paperless}
ports: [{name: http, port: 8000, targetPort: http}]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: paperless
namespace: paperless-ngx
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
rules:
- host: paper.brunner.ninja
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: paperless
port: {name: http}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: scanner-config
namespace: paperless-ngx
data:
config.local.js: |
const fs = require('node:fs/promises');
const path = require('node:path');
const crypto = require('node:crypto');
const output = process.env.SCAN_OUTPUT_DIR || '/var/lib/scanservjs/output';
const consume = process.env.PAPERLESS_CONSUME_DIR || '/paperless-consume';
module.exports = {
actions: [{
name: 'Send to Paperless',
async execute(fileInfo) {
const source = await fs.realpath(fileInfo.fullname);
if (!source.startsWith(output + '/') || path.extname(source).toLowerCase() !== '.pdf') {
throw new Error('Only staged PDF files can be sent to Paperless');
}
const name = `${Date.now()}-${crypto.randomBytes(6).toString('hex')}-${path.basename(source)}`;
const destination = path.join(consume, name);
const pending = destination + '.part';
try {
await fs.copyFile(source, pending);
await fs.rename(pending, destination);
await fs.unlink(source);
} catch (error) {
await fs.rm(pending, {force: true});
throw error;
}
},
}],
};
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: scanner
namespace: paperless-ngx
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels: {app: scanner}
template:
metadata:
labels: {app: scanner}
spec:
automountServiceAccountToken: false
securityContext:
supplementalGroups: [1000]
initContainers:
- name: prepare-output
image: busybox:1.37.0
command: [sh, -c, 'mkdir -p /volume/scanner-staging && chown 102:100 /volume/scanner-staging && chmod 775 /volume/scanner-staging && chmod g+w /volume/consume']
volumeMounts:
- {name: data, mountPath: /volume}
containers:
- name: scanner
image: sbs20/scanservjs:3.3.0
command: [sh, -c, "sed -i '/^\\[options\\]/a discovery = disable' /etc/sane.d/airscan.conf && exec /entrypoint.sh"]
env:
- {name: AIRSCAN_DEVICES, value: '"HP OfficeJet Pro 8020" = http://192.168.4.189:8080/eSCL, eSCL'}
ports: [{name: http, containerPort: 8080}]
volumeMounts:
- {name: data, mountPath: /var/lib/scanservjs/output, subPath: scanner-staging}
- {name: data, mountPath: /paperless-consume, subPath: consume}
- {name: config, mountPath: /etc/scanservjs/config.local.js, subPath: config.local.js, readOnly: true}
startupProbe:
httpGet: {path: /, port: http}
periodSeconds: 5
failureThreshold: 60
readinessProbe:
httpGet: {path: /, port: http}
periodSeconds: 10
livenessProbe:
httpGet: {path: /, port: http}
periodSeconds: 30
resources:
requests: {cpu: 100m, memory: 256Mi}
limits: {memory: 2Gi}
volumes:
- name: data
persistentVolumeClaim: {claimName: paperless-data}
- name: config
configMap: {name: scanner-config}
---
apiVersion: v1
kind: Service
metadata:
name: scanner
namespace: paperless-ngx
spec:
selector: {app: scanner}
ports: [{name: http, port: 8080, targetPort: http}]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: scanner
namespace: paperless-ngx
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: scanner.brunner.ninja
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: scanner
port: {name: http}