feat(k8s/paperless): add paperless-ngx stack (deployment scaled to 0 for data migration)

This commit is contained in:
2026-03-11 13:57:57 +02:00
parent 07fa20795f
commit 09caddd10a
17 changed files with 865 additions and 2 deletions

View File

@@ -0,0 +1,141 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: paperless-db-backup
namespace: paperless
labels:
app: paperless-backup
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
metadata:
labels:
app: paperless-backup
spec:
restartPolicy: OnFailure
initContainers:
- name: pg-dump
image: postgres:18
env:
- name: PGHOST
value: paperless-db
- name: PGUSER
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_USERNAME
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_PASSWORD
- name: PGDATABASE
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_DATABASE_NAME
command:
- sh
- -c
- pg_dump --clean --if-exists > /backup/dump.sql
volumeMounts:
- name: backup-tmp
mountPath: /backup
containers:
- name: resticprofile
image: creativeprojects/resticprofile:0.32.0
command:
- sh
- -c
- |
resticprofile -c /secrets/profiles.yaml -n paperless-db backup
resticprofile -c /secrets/profiles.yaml -n paperless-db copy
env:
- name: B2_ACCOUNT_ID
valueFrom:
secretKeyRef:
name: paperless-backup-config
key: B2_ACCOUNT_ID
- name: B2_ACCOUNT_KEY
valueFrom:
secretKeyRef:
name: paperless-backup-config
key: B2_ACCOUNT_KEY
volumeMounts:
- name: secrets
mountPath: /secrets
readOnly: true
- name: backup-tmp
mountPath: /backup
volumes:
- name: secrets
secret:
secretName: paperless-backup-config
- name: backup-tmp
emptyDir: {}
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: paperless-media-backup
namespace: paperless
labels:
app: paperless-backup
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
metadata:
labels:
app: paperless-backup
spec:
restartPolicy: OnFailure
containers:
- name: resticprofile
image: creativeprojects/resticprofile:0.32.0
command:
- sh
- -c
- |
resticprofile -c /secrets/profiles.yaml -n paperless-media backup
resticprofile -c /secrets/profiles.yaml -n paperless-media copy
env:
- name: B2_ACCOUNT_ID
valueFrom:
secretKeyRef:
name: paperless-backup-config
key: B2_ACCOUNT_ID
- name: B2_ACCOUNT_KEY
valueFrom:
secretKeyRef:
name: paperless-backup-config
key: B2_ACCOUNT_KEY
volumeMounts:
- name: secrets
mountPath: /secrets
readOnly: true
- name: media
mountPath: /media
readOnly: true
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumes:
- name: secrets
secret:
secretName: paperless-backup-config
- name: media
persistentVolumeClaim:
claimName: paperless-media

View File

@@ -0,0 +1,40 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless-gotenberg
namespace: paperless
labels:
app: paperless-gotenberg
spec:
replicas: 1
selector:
matchLabels:
app: paperless-gotenberg
template:
metadata:
labels:
app: paperless-gotenberg
spec:
securityContext:
# gotenberg image uses a non-numeric username so runAsNonRoot cannot be verified by kubelet
seccompProfile:
type: RuntimeDefault
containers:
- name: gotenberg
image: gotenberg/gotenberg:8
command:
- gotenberg
- --chromium-disable-javascript=true
- --chromium-allow-list=file:///tmp/.*
env:
- name: TZ
value: Europe/Kyiv
ports:
- containerPort: 3000
name: http
resources:
requests:
cpu: 50m
memory: 256Mi
limits:
memory: 1Gi

View File

@@ -0,0 +1,45 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless-redis
namespace: paperless
labels:
app: paperless-redis
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: paperless-redis
template:
metadata:
labels:
app: paperless-redis
spec:
securityContext:
# redis image starts as root to set up permissions then drops to the redis user internally
seccompProfile:
type: RuntimeDefault
containers:
- name: redis
image: redis:8
env:
- name: TZ
value: Europe/Kyiv
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
cpu: 20m
memory: 64Mi
limits:
memory: 256Mi
volumes:
- name: data
persistentVolumeClaim:
claimName: paperless-redis

View File

@@ -0,0 +1,36 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless-tika
namespace: paperless
labels:
app: paperless-tika
spec:
replicas: 1
selector:
matchLabels:
app: paperless-tika
template:
metadata:
labels:
app: paperless-tika
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: tika
image: apache/tika:3.2.3.0
env:
- name: TZ
value: Europe/Kyiv
ports:
- containerPort: 9998
name: http
resources:
requests:
cpu: 50m
memory: 256Mi
limits:
memory: 1Gi

View File

@@ -0,0 +1,128 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: paperless
namespace: paperless
labels:
app: paperless
spec:
replicas: 0
strategy:
type: Recreate
selector:
matchLabels:
app: paperless
template:
metadata:
labels:
app: paperless
spec:
enableServiceLinks: false
securityContext:
# paperless-ngx starts as root to remap USERMAP_UID/GID — runAsNonRoot is intentionally omitted
seccompProfile:
type: RuntimeDefault
containers:
- name: paperless
image: ghcr.io/paperless-ngx/paperless-ngx:2.20
ports:
- containerPort: 8000
name: http
env:
- name: PAPERLESS_REDIS
value: redis://paperless-redis:6379
- name: PAPERLESS_DBHOST
value: paperless-db
- name: PAPERLESS_DBUSER
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_USERNAME
- name: PAPERLESS_DBPASS
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_PASSWORD
- name: PAPERLESS_DBNAME
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_DATABASE_NAME
- name: PAPERLESS_SECRET_KEY
valueFrom:
secretKeyRef:
name: paperless-credentials
key: PAPERLESS_SECRET_KEY
- name: PAPERLESS_SOCIALACCOUNT_PROVIDERS
valueFrom:
secretKeyRef:
name: paperless-credentials
key: PAPERLESS_SOCIALACCOUNT_PROVIDERS
- name: PAPERLESS_TIKA_ENABLED
value: "1"
- name: PAPERLESS_TIKA_GOTENBERG_ENDPOINT
value: http://paperless-gotenberg:3000
- name: PAPERLESS_TIKA_ENDPOINT
value: http://paperless-tika:9998
- name: PAPERLESS_OCR_LANGUAGE
value: ukr+eng
- name: PAPERLESS_OCR_LANGUAGES
value: ukr rus
- name: PAPERLESS_TIME_ZONE
value: Europe/Kyiv
- name: PAPERLESS_URL
value: https://${PAPERLESS_HOST}
- name: PAPERLESS_CONSUMER_BARCODE_SCANNER
value: ZXING
- name: PAPERLESS_TASK_WORKERS
value: "2"
- name: PAPERLESS_CONSUMER_POLLING
value: "10"
- name: USERMAP_UID
value: "1027"
- name: USERMAP_GID
value: "100"
- name: PAPERLESS_APPS
value: allauth.socialaccount.providers.openid_connect
- name: PAPERLESS_SOCIALACCOUNT_ALLOW_SIGNUPS
value: "false"
volumeMounts:
- name: data
mountPath: /usr/src/paperless/data
- name: media
mountPath: /usr/src/paperless/media
- name: consume
mountPath: /usr/src/paperless/consume
- name: export
mountPath: /usr/src/paperless/export
livenessProbe:
httpGet:
port: 8000
path: /api/
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
port: 8000
path: /api/
initialDelaySeconds: 30
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
memory: 5Gi
volumes:
- name: data
persistentVolumeClaim:
claimName: paperless-data
- name: media
persistentVolumeClaim:
claimName: paperless-media
- name: consume
persistentVolumeClaim:
claimName: paperless-consume
- name: export
persistentVolumeClaim:
claimName: paperless-export

View File

@@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: paperless
namespace: paperless
annotations:
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- ${PAPERLESS_HOST}
secretName: paperless-tls
rules:
- host: ${PAPERLESS_HOST}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: paperless
port:
number: 8000

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: paperless

View File

@@ -0,0 +1,136 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: paperless
spec:
podSelector: {}
policyTypes:
- Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-controller
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: traefik
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-db
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless-db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: paperless
- podSelector:
matchLabels:
app: paperless-backup
ports:
- port: 5432
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-redis
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless-redis
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: paperless
ports:
- port: 6379
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-gotenberg
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless-gotenberg
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: paperless
ports:
- port: 3000
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-tika
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless-tika
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: paperless
ports:
- port: 9998
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backup-egress
namespace: paperless
spec:
podSelector:
matchLabels:
app: paperless-backup
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
- ports:
- port: 8000
protocol: TCP
- ports:
- port: 443
protocol: TCP
- ports:
- port: 5432
protocol: TCP
to:
- podSelector:
matchLabels:
app: paperless-db

View File

@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: paperless-consume-nfs
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
storageClassName: ""
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- intr
- timeo=30
- retrans=3
nfs:
server: synology.storage.lviv
path: ${PAPERLESS_CONSUME_NFS_PATH}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-consume
namespace: paperless
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
volumeName: paperless-consume-nfs
resources:
requests:
storage: 50Gi

View File

@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: paperless-data-nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: ""
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- intr
- timeo=30
- retrans=3
nfs:
server: synology.storage.lviv
path: ${PAPERLESS_DATA_NFS_PATH}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-data
namespace: paperless
spec:
accessModes:
- ReadWriteOnce
storageClassName: ""
volumeName: paperless-data-nfs
resources:
requests:
storage: 10Gi

View File

@@ -0,0 +1,33 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: paperless-media-nfs
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
storageClassName: ""
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- intr
- timeo=30
- retrans=3
nfs:
server: synology.storage.lviv
path: ${PAPERLESS_MEDIA_NFS_PATH}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-media
namespace: paperless
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
volumeName: paperless-media-nfs
resources:
requests:
storage: 100Gi

View File

@@ -0,0 +1,25 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-export
namespace: paperless
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-synology-ssd
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: paperless-redis
namespace: paperless
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-synology-ssd
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Secret
metadata:
name: paperless-backup-config
namespace: paperless
stringData:
profiles.yaml: ENC[AES256_GCM,data:RMCLu/OXCXil3GXg/OK/iknpJFDe0jN9V9kF3VY27VkiKhP+VibgGgXL1e16uRahQgiMyUDjrqSA/gLF43xPW1NJL+igr4hn2gJC8CWdu8QVbWWFwswJJMkaEFrIfFHI4RuL9KOd8XOE1ZUSoV33kGKP2kVgRays5H2oTkafBjGzFFPt5kVbj90Q0J4Pn09NcR1Ik7m1aqzSS5Ci7rHnlvXVUPubT9mdZSAChPuCUG34JYLV71SD5jvO1rFyhHWaC//oc6K18v4l2C2t+JPBEzJJd8eVZ+XnbZk8+IDDyHT0/JzInZI3bMj6jva5Y4fIS4044O+LLuiAsD6V7Ax1MTM3ORbDZciP/Kr0VQY/6EVs1wbFccJzPCQmVljWeBW3GzqjbuMzOkvUGCmrW1UbcK47mDqhava3oi4Nz/cTuHAM9pqc1R8keC0p3eN/ekZTyd+ByDl8Cfm0ec6YobCI8kIhmadsPPreO/x6vDTCUHmoqeabO54ISixvozEla06vMMuG/0cEqWrtKFBCWw/llnf/RaFskqZ++5kA6NfizZGohhvqBv9TLEsD/oFyBY1itHFPpmi5kcYZhp32GDUCa7nn4A8UfLRu1XGHl5u4wapZ9JPlzCy88dWjQN9jjpINwqkj9CMmNf99SLUzGEBocSuD5JkhS1DnP/17G7qu0jQnISZ83xHlyOzDVwnZL2Fxthn158p7jAwI+qjzsk+QFtXZsxq4WuN+kVUyjZPu8pz7qOWr9Y6H3nAOP1RBrAEd6fjOoAs5wQNePLrHxiMWM99sXf4fLWY59+wvLMhfBvN+yCDK9QaENu04W/5QElE/Htu07pRZyiPQpSCizntbttlIFgXQKKcz88Z0oq2pQmuwPCXQ66hfcoQHK55p9ganhOi65jVPdCDXhXrBdzpGg+LB7zrUEXNw+wixTEH+RkFrKZX3k4SwrQZriFtXaNun/cHfPW8qe/wX9N5wPtEy0QXFkKZeFRWt+6fO9Zx2Zw9jUEDgDNovWoxFQralKWeNPen97Na8DyAzhNBWNFSfc0+V/mP7SvjHO3U6QHW1bjHLB7NPOEw5vP8kLQCVkeUvhW6bneSHboCz8Orw2YUNR2qqLr88Vt47j5yEa8uJf3zX1LFBlIcK2/nACsgwdCEuHkZFSKncthAzzWJq+biJ18bSAbLdHtPGhms7bFd/lXxXdCQ4qzQUUbZm725Lw2W+oB3pPB/qR+TcW2e4bBTHtCTOtYeN/nfih7lzH+Y93ceGSVLsSNwy4tUZbZ/kJqmT/0hlew==,iv:u22vr6RJs9P3Ld6QF2tc8uWsxspVhVhOZPr+8jGEUzs=,tag:UAA8IvcNgjTnXCAwEC6WKw==,type:str]
restic-password-nas: ENC[AES256_GCM,data:giPA+M18Hy4YKZD1vdB3ZH5cHtjF/4BU1pFVswLI+eFIBVYnBvPBUwQw0veuDHlT2uSZjRxgwietXOFsrQqhAw==,iv:bRIyljpontXfg+aGQSFO2xOd+5qr9A1jnz7lFSHPOmE=,tag:uDq7jrv8amQKK6xhxULbSQ==,type:str]
restic-password-b2: ENC[AES256_GCM,data:nh43a0h7esMgHD9l4HcS2D3hzveoP9/KVEgHDgOtOIxDYwb1t2W7fsHSiNk7TKAXg0t/OiS5xV8cKF5xCGakvw==,iv:8kiKWYRHiMwQJzZcwr8rVjvvlpjAGf+p/1GZHbDSGqw=,tag:QvakLN/wCciPqj2tC8dM+A==,type:str]
B2_ACCOUNT_ID: ENC[AES256_GCM,data:AXnixNRDDfSVsmzv7kiSIfpWyeeA/0OYNA==,iv:eGpFqxiV3DOz4DcldsC3gbF0bLyScaljagWXicI29nY=,tag:063z8kIC0vVTqqzMctItJw==,type:str]
B2_ACCOUNT_KEY: ENC[AES256_GCM,data:N/DqdOJRWow7WxSnfkMpV8KmqU1lMNuMeju7vvDW/g==,iv:nP076fQTEGmTkPlHFns/yWsPL0IWyRZ8YzsoW3PkP0w=,tag:dF/7LzqOC61pziYGmaKAEg==,type:str]
sops:
age:
- recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBacmJVbllKQ3diS1RPQXZq
ZXlPOGlRMXgxUTdTbHI2SDQwZjE2V1ZCU0M4ClNjZ01jcVRxQklWL3MyVFd6d2VN
VkYxejlEejV2VjVsRUxiSVNHaC92aU0KLS0tIDhrUjNPRHJPUnFKV2ZaaFc4VUxB
aUp3cTlCZDhtWU5ub2d6UmhobnZiS1EKr1ua46Om9jtPhkUJsT0xA64Cn+uCK3T6
wgvx/dtvSgiZhctA/WrUneeRcSmmQmV8GywA4moGYfyRy+8WmyGdhQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-03-11T12:59:46Z"
mac: ENC[AES256_GCM,data:W+7ZEiJn+FAPwFGMBkDojOncT3hs6ZGjLmKZHfK0laVLmqFQVw83nov/NeCGMtWPI+57KCrVwoinhdKBAzW090sHE9BdxsolcT7KgyIQvXBjcrlXtWK4jLijAwiT4hbdr266LvON+MaM/Qm5RsFWKNZVThxp8AxhRXalfWKYkJA=,iv:WMt79oGLg9G4RZZvXro3WVtnCvgDA+rDNEqyzngPylg=,tag:KXV/RTlmKHIbkP2j6dAA3g==,type:str]
encrypted_regex: ^(data|stringData|email)$
version: 3.12.1

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Secret
metadata:
name: paperless-credentials
namespace: paperless
stringData:
DB_USERNAME: ENC[AES256_GCM,data:rQ+OaNpb1oMv,iv:GA3HVRFNeY0Sk2h3aUKsDidDmUIHsDY4jBB0L2bXXi0=,tag:I5+Th/sdPDXX8nTUR5gn6Q==,type:str]
DB_PASSWORD: ENC[AES256_GCM,data:SOj7NJMaLypZXO/35ZLQOvEtVzTG0hb8oUHw7umFQdM1pLT28u8h6OPV8gaxccmPoSKb5tDEfsPQFybxGPcv5w==,iv:0vTapzDX2Abq/YZHYph+m3ERHGVXIEjzS/amAii00bE=,tag:vGy6y+rYAq4RTeWj6Lwhsw==,type:str]
DB_DATABASE_NAME: ENC[AES256_GCM,data:uLS32XZBHNuz,iv:TkynDQNDafivNROzpa1CJlrQXzPN+K/I9rSwStJ4hS4=,tag:Xp9nWh9R5u4s6GbleW8Y2g==,type:str]
PAPERLESS_SECRET_KEY: ENC[AES256_GCM,data:xda21hgfizCH5nBoJZIGWF7hooldk532IW+LcXK5dSmToRNmZB9JS9xW6592c7sFsBWeDakN9w5bR6r/ROzg1EOTNoYBJSD/9MpAUvx3zFMrQnexFFS3BxR2Gg021kg9y/VZDivw9+y/K/T4YRrQkitcgaO5CPOW6h6w7zyQ9cE=,iv:L9nhq6kl4zJAY8qt/7mOmS0jhSr62QpAMAVRA21/o10=,tag:eZFjcZ5bA3MbVLTY+ilJgw==,type:str]
PAPERLESS_SOCIALACCOUNT_PROVIDERS: ENC[AES256_GCM,data:71iqbb97bSVJaeGzrW6WvkJTyILyEMWCYR263/k9JcozdxV/BM0S/1MM5KAiMJSoNLCl+p1ve3N+cH4CUbvsLnvvEbVuVRlkZ3EbvDLiepJFQjobKOHQKKV1ag844Lboa4KgPC1Q0pCoD+7w5GAA1f19GBesqfhP6OhozXJ3Q4xlU9rbF+kJM6f5gTbEji+A8SWa9J0iDk1r1Ehm9Unlq78KcCdqH8hDSge0+dKezlJ0PaoGnvu+dwiuxa9TkZClUU3CjyXuxcnkgBr3KbCZKsWzsLAtwjkM1ifff22v2nzGOaZDbjdUdc5jmgf3KQr6Sp4N68RisTo/OWP7y9EpHO2vk83UuzrTBdxpMQGfzqXj16IztIyrSVRsbi6Hvb3wXBV3I7J+fxDA9c0HKYa9YLJaQ3Yz+X8Pzdpwnrub5ZC5uZosYya9bb1KPzVGzLtswWTYS6j3AirKyMGyTSKF60id2+Z+rl7VvWytgQ==,iv:Y7Zi5Q4cEcTbLMUUH7BJ5p0OqBYRwl4jsETJ7cASG0Y=,tag:QySlG72Q/f2MoNWWN7JWWg==,type:str]
sops:
age:
- recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRbXQ4VzBrQzJPeHBHSzdS
d3pvMkxXS1NoS3pYVGFoT1p1b0prRklXaWlRCmN0cnR4dy9KTHhEM2MvWEsxMkJS
dHljeDY3RnIwRDJOLzFHU1pDNXhEaU0KLS0tIElXdHFtQUphQXNoVHljZkZUSzRR
Y1EraGNRU0RDTVpoeG94WjZuYzJRczQKecyrOUBpDBPddN8H7IqCttJ0/yhIr/Og
QOjtSNjJJF23Wtbtty/4VdLzETnhC3bBipORVattkpVqnSbXOEGd6g==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-03-11T10:54:47Z"
mac: ENC[AES256_GCM,data:j9m8LLDSBSxWHOQnYvl80tWCb20XUll60M3+vgWjfCOqXzKyYDOR4LQJreZncsSuw9Y7Ua1tK8/ZgDP4upOTx52He+lEL53wETuTzQCUzvrY9rkCtcR5A5EGWyusbn729+pk7HFxIvibZzRVhitP9z8w0+J5V13nUe/xMAsJQ5U=,iv:IyNbAoSNE6xuDJdcAPeCDt3EVuTAwkXpoQVXByjkN1Y=,tag:N6EHm3g0tkyz4uI9MZ9nYA==,type:str]
encrypted_regex: ^(data|stringData|email)$
version: 3.12.1

View File

@@ -0,0 +1,64 @@
apiVersion: v1
kind: Service
metadata:
name: paperless
namespace: paperless
spec:
selector:
app: paperless
ports:
- port: 8000
targetPort: 8000
name: http
---
apiVersion: v1
kind: Service
metadata:
name: paperless-db
namespace: paperless
spec:
clusterIP: None
selector:
app: paperless-db
ports:
- port: 5432
targetPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: paperless-redis
namespace: paperless
spec:
selector:
app: paperless-redis
ports:
- port: 6379
targetPort: 6379
name: redis
---
apiVersion: v1
kind: Service
metadata:
name: paperless-gotenberg
namespace: paperless
spec:
selector:
app: paperless-gotenberg
ports:
- port: 3000
targetPort: 3000
name: http
---
apiVersion: v1
kind: Service
metadata:
name: paperless-tika
namespace: paperless
spec:
selector:
app: paperless-tika
ports:
- port: 9998
targetPort: 9998
name: http

View File

@@ -0,0 +1,65 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: paperless-db
namespace: paperless
labels:
app: paperless-db
spec:
serviceName: paperless-db
replicas: 1
selector:
matchLabels:
app: paperless-db
template:
metadata:
labels:
app: paperless-db
spec:
securityContext:
runAsUser: 999
runAsGroup: 999
fsGroup: 999
containers:
- name: postgres
image: postgres:18
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_USERNAME
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: paperless-credentials
key: DB_DATABASE_NAME
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: TZ
value: Europe/Kyiv
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
resources:
requests:
cpu: 50m
memory: 256Mi
limits:
memory: 1Gi
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-synology-ssd
resources:
requests:
storage: 5Gi