From 48ed48752f155646246f823cfbfb954d24b31b55 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Fri, 13 Jan 2023 21:30:49 -0600 Subject: [PATCH] paperless-ngx: Deploy application *Paperless-ngx* is a document management system. It provides tools for organizing, indexing, and searching documents, including OCR. --- paperless-ngx/README.md | 26 +++ paperless-ngx/ingress.yaml | 36 +++ paperless-ngx/kustomization.yaml | 24 ++ paperless-ngx/paperless-ngx.yaml | 388 +++++++++++++++++++++++++++++++ 4 files changed, 474 insertions(+) create mode 100644 paperless-ngx/README.md create mode 100644 paperless-ngx/ingress.yaml create mode 100644 paperless-ngx/kustomization.yaml create mode 100644 paperless-ngx/paperless-ngx.yaml diff --git a/paperless-ngx/README.md b/paperless-ngx/README.md new file mode 100644 index 0000000..71948d3 --- /dev/null +++ b/paperless-ngx/README.md @@ -0,0 +1,26 @@ +# Paperless-ngx + +> [*Paperless-ngx*][0] is a community-supported open-source document management +> system that transforms your physical documents into a searchable online +> archive so you can keep, well, less paper. + +## Deploy with `kustomize` + +```sh +kubectl apply -k paperless-ngx +``` + +Generic resources, including the persistent volumes and pods, are defined in +`paperless-ngx/paperless-ngx.yaml`. Environment-specific overrides are +supplied in `paperless-ngx/kustomization.yaml`. An Ingress resource is +configured in `paperless-ngx/ingress.yaml`. + +This deployment uses SQLite as the database engine. *Paperless-ngx* supports +other engines, but SQLite is fine for a single-instance deployment with only a +small number of documents. + +Authentication via "HTTP remote user" is enabled, and the Ingress is configured +to use Authelia. This provides a single sign-on experince, since +*Paperless-ngx* does not currently support LDAP or OAuth/OpenID Connect. + +[0]: https://docs.paperless-ngx.com/ diff --git a/paperless-ngx/ingress.yaml b/paperless-ngx/ingress.yaml new file mode 100644 index 0000000..e558a09 --- /dev/null +++ b/paperless-ngx/ingress.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: '0' + nginx.ingress.kubernetes.io/auth-method: GET + nginx.ingress.kubernetes.io/auth-url: http://authelia.authelia.svc.cluster.local:9091/api/verify + nginx.ingress.kubernetes.io/auth-signin: https://auth.pyrocufflink.blue/?rm=$request_method + nginx.ingress.kubernetes.io/auth-response-headers: Remote-User,Remote-Name,Remote-Groups,Remote-Email + nginx.ingress.kubernetes.io/auth-snippet: | + proxy_set_header X-Forwarded-Method $request_method; + name: paperless-ngx + namespace: paperless-ngx +spec: + ingressClassName: nginx + tls: + - hosts: + - paperless.pyrocufflink.blue + rules: + - host: paperless.pyrocufflink.blue + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: paperless-ngx + port: + name: http + diff --git a/paperless-ngx/kustomization.yaml b/paperless-ngx/kustomization.yaml new file mode 100644 index 0000000..4415c77 --- /dev/null +++ b/paperless-ngx/kustomization.yaml @@ -0,0 +1,24 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- paperless-ngx.yaml +- ingress.yaml + +patches: +- target: + kind: StatefulSet + name: paperless-ngx + patch: |- + kind: StatefulSet + metadata: + name: paperless-ngx + spec: + template: + spec: + containers: + - name: paperless-ngx + env: + - name: PAPERLESS_URL + value: https://paperless.pyrocufflink.blue + diff --git a/paperless-ngx/paperless-ngx.yaml b/paperless-ngx/paperless-ngx.yaml new file mode 100644 index 0000000..78d96a4 --- /dev/null +++ b/paperless-ngx/paperless-ngx.yaml @@ -0,0 +1,388 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: paperless-ngx + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: paperless-cmd + namespace: paperless-ngx + labels: + app.kubernetes.io/name: paperless_cmd.sh + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +data: + paperless_cmd.sh: |+ + #!/bin/sh + + exec /usr/local/bin/supervisord -c /etc/supervisord.conf --user paperless + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis + namespace: paperless-ngx + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: paperless-ngx + namespace: paperless-ngx + labels: + app.kubernetes.io/name: data + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx + name: redis + namespace: paperless-ngx +spec: + ports: + - name: redis + port: 6379 + selector: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + type: ClusterIP + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx + name: paperless-ngx + namespace: paperless-ngx +spec: + ports: + - name: http + port: 8000 + selector: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + type: ClusterIP + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: gotenberg + app.kubernetes.io/component: gotenberg + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx + name: gotenberg + namespace: paperless-ngx +spec: + ports: + - name: gotenberg + port: 3000 + selector: + app.kubernetes.io/name: gotenberg + app.kubernetes.io/component: gotenberg + app.kubernetes.io/instance: paperless-ngx + type: ClusterIP + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: tika + app.kubernetes.io/component: tika + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx + name: tika + namespace: paperless-ngx +spec: + ports: + - name: tika + port: 9998 + selector: + app.kubernetes.io/name: tika + app.kubernetes.io/component: tika + app.kubernetes.io/instance: paperless-ngx + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis + namespace: paperless-ngx + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + serviceName: redis + selector: + matchLabels: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + template: + metadata: + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/component: redis + app.kubernetes.io/instance: paperless-ngx + spec: + containers: + - name: redis + image: docker.io/library/redis:7 + imagePullPolicy: IfNotPresent + ports: + - name: redis + containerPort: 6379 + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + runAsUser: 1000 + runAsGroup: 1000 + volumeMounts: + - name: redisdata + mountPath: /data + subPath: data + - name: tmp + mountPath: /tmp + securityContext: + fsGroup: 1000 + volumes: + - name: redisdata + persistentVolumeClaim: + claimName: redis + - name: tmp + emptyDir: + +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: paperless-ngx + namespace: paperless-ngx + labels: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + serviceName: paperless-ngx + selector: + matchLabels: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + template: + metadata: + labels: + app.kubernetes.io/name: paperless-ngx + app.kubernetes.io/component: paperless-ngx + app.kubernetes.io/instance: paperless-ngx + spec: + containers: + - name: paperless-ngx + image: ghcr.io/paperless-ngx/paperless-ngx:1.11.3 + imagePullPolicy: IfNotPresent + env: + - name: PAPERLESS_REDIS + value: redis://redis:6379 + - name: PAPERLESS_TIKA_ENABLED + value: '1' + - name: PAPERLESS_TIKA_GOTENBERG_ENDPOINT + value: http://gotenberg:3000 + - name: PAPERLESS_TIKA_ENDPOINT + value: http://tika:9998 + - name: PAPERLESS_ALLOWED_HOSTS + value: '*' + - name: PAPERLESS_ENABLE_HTTP_REMOTE_USER + value: '1' + ports: + - name: http + containerPort: 8000 + startupProbe: + httpGet: + port: 8000 + path: / + failureThreshold: 30 + timeoutSeconds: 3 + periodSeconds: 3 + initialDelaySeconds: 10 + readinessProbe: + httpGet: + port: 8000 + path: / + failureThreshold: 5 + timeoutSeconds: 10 + periodSeconds: 30 + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + runAsUser: 1000 + runAsGroup: 1000 + volumeMounts: + - name: cmd + mountPath: /usr/local/bin/paperless_cmd.sh + subPath: paperless_cmd.sh + - name: data + mountPath: /usr/src/paperless/data + subPath: data + - name: data + mountPath: /usr/src/paperless/media + subPath: media + - name: data + mountPath: /usr/src/paperless/export + subPath: export + - name: data + mountPath: /usr/src/paperless/consume + subPath: consume + - name: tmp + mountPath: /tmp + - name: run + mountPath: /run/supervisord + - name: logs + mountPath: /var/log/supervisord + subPath: supervisord + securityContext: + fsGroup: 1000 + volumes: + - name: cmd + configMap: + name: paperless-cmd + defaultMode: 0755 + - name: data + persistentVolumeClaim: + claimName: paperless-ngx + - name: logs + empytDir: + - name: tmp + emptyDir: + medium: Memory + - name: run + emptyDir: + medium: Memory + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gotenberg + namespace: paperless-ngx + labels: + app.kubernetes.io/name: gotenberg + app.kubernetes.io/component: gotenberg + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + selector: + matchLabels: + app.kubernetes.io/name: gotenberg + app.kubernetes.io/component: gotenberg + app.kubernetes.io/instance: paperless-ngx + template: + metadata: + labels: + app.kubernetes.io/name: gotenberg + app.kubernetes.io/component: gotenberg + app.kubernetes.io/instance: paperless-ngx + spec: + containers: + - name: gotenberg + image: docker.io/gotenberg/gotenberg:7.6 + imagePullPolicy: IfNotPresent + command: + - gotenberg + - --chromium-disable-javascript=true + - --chromium-allow-list=file:///tmp/.* + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + runAsUser: 1000 + runAsGroup: 1000 + volumeMounts: + - name: tmp + mountPath: /tmp + securityContext: + fsGroup: 1000 + volumes: + - name: tmp + emptyDir: + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tika + namespace: paperless-ngx + labels: + app.kubernetes.io/name: tika + app.kubernetes.io/component: tika + app.kubernetes.io/instance: paperless-ngx + app.kubernetes.io/part-of: paperless-ngx +spec: + selector: + matchLabels: + app.kubernetes.io/name: tika + app.kubernetes.io/component: tika + app.kubernetes.io/instance: paperless-ngx + template: + metadata: + labels: + app.kubernetes.io/name: tika + app.kubernetes.io/component: tika + app.kubernetes.io/instance: paperless-ngx + spec: + containers: + - name: tika + image: ghcr.io/paperless-ngx/tika:2.5.0-minimal + imagePullPolicy: IfNotPresent + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + runAsUser: 1000 + runAsGroup: 1000 + volumeMounts: + - name: tmp + mountPath: /tmp + securityContext: + fsGroup: 1000 + volumes: + - name: tmp + emptyDir: