diff --git a/README.md b/README.md index 9fce319e..e9817b66 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Other ways are documented - Using the [nix](https://nixos.org/nix) package manager as [described here](https://docspell.org/docs/install/installing/#nix). A NixOS module is available, too. +- Use the [Kubernetes](./kubernetes/README.md) configuration. ## Documentation diff --git a/kubernetes/README.md b/kubernetes/README.md new file mode 100644 index 00000000..9632673b --- /dev/null +++ b/kubernetes/README.md @@ -0,0 +1,62 @@ +# Docspell Kubernetes Setup + +This folder contains the necessary Kubernetes manifests, as well as a [Kustomization](https://kustomize.io/), to deploy docspell to a Kubernetes cluster. + +## Using Kustomize + +To deploy a basic installation using Kustomize, you can use the following command: + +``` shell +kubectl apply -k https://raw.githubusercontent.com/eikek/docspell/master/kubernetes +``` + +For a more advanced and production ready setup, create your own kustomization.yaml, changing the secret value and replica counts as necessary: + +``` yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- github.com/eikek/docspell.git//kubernetes?timeout=90s&ref=master +patches: +- target: + kind: Deployment + name: restserver + patch: |- + - op: replace + path: /spec/replicas + value: 2 + - op: replace + path: /spec/template/spec/containers/0/image + value: docspell/restserver:v0.40.0 +- target: + kind: Deployment + name: joex + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: docspell/joex:v0.40.0 +- target: + kind: Secret + name: restserver-secrets + patch: |- + - op: replace + path: /data/DOCSPELL_SERVER_BACKEND_JDBC_PASSWORD + value: ZGJwYXNzMg== # dbpass2 + - op: replace + path: /data/DOCSPELL_JOEX_JDBC_PASSWORD + value: ZGJwYXNzMg== # dbpass2 +``` + +And apply your kustomization: + +``` shell +kubectl apply -k . +``` + +## Using Kubernetes manifests + +To deploy a basic installation using the Kubernetes manifests, you can use the following command: + +``` shell +kubectl apply -f https://raw.githubusercontent.com/eikek/docspell/master/kubernetes +``` \ No newline at end of file diff --git a/kubernetes/deployment.yaml b/kubernetes/deployment.yaml new file mode 100644 index 00000000..47cc52a9 --- /dev/null +++ b/kubernetes/deployment.yaml @@ -0,0 +1,107 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: restserver +spec: + replicas: 1 + selector: + matchLabels: + app: restserver + template: + metadata: + labels: + app: restserver + spec: + containers: + - name: restserver + image: docspell/restserver + ports: + - containerPort: 7880 + envFrom: + - configMapRef: + name: restserver-config + - secretRef: + name: restserver-secrets + env: + - name: DOCSPELL_SERVER_INTERNAL__URL + value: "http://restserver:7880" + - name: DOCSPELL_SERVER_BACKEND_JDBC_URL + value: "jdbc:postgresql://postgres:5432/dbname" + - name: DOCSPELL_SERVER_BIND_ADDRESS + value: "0.0.0.0" + - name: DOCSPELL_SERVER_FULL__TEXT__SEARCH_ENABLED + value: "true" + - name: DOCSPELL_SERVER_FULL__TEXT__SEARCH_SOLR_URL + value: "http://solr:8983/solr/docspell" + - name: DOCSPELL_SERVER_INTEGRATION__ENDPOINT_ENABLED + value: "true" + - name: DOCSPELL_SERVER_INTEGRATION__ENDPOINT_HTTP__HEADER_ENABLED + value: "true" + - name: DOCSPELL_SERVER_BACKEND_SIGNUP_MODE + value: "open" + - name: DOCSPELL_SERVER_BACKEND_ADDONS_ENABLED + value: "false" + resources: + limits: + cpu: '1' + memory: 1Gi + requests: + cpu: '0.5' + memory: 512Mi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: joex +spec: + replicas: 1 + selector: + matchLabels: + app: joex + template: + metadata: + labels: + app: joex + spec: + containers: + - name: joex + image: docspell/joex + ports: + - containerPort: 7878 + envFrom: + - configMapRef: + name: joex-config + - secretRef: + name: joex-secrets + env: + - name: DOCSPELL_JOEX_APP__ID + value: "joex1" + - name: DOCSPELL_JOEX_PERIODIC__SCHEDULER_NAME + value: "joex1" + - name: DOCSPELL_JOEX_SCHEDULER_NAME + value: "joex1" + - name: DOCSPELL_JOEX_BASE__URL + value: "http://joex:7878" + - name: DOCSPELL_JOEX_BIND_ADDRESS + value: "0.0.0.0" + - name: DOCSPELL_JOEX_FULL__TEXT__SEARCH_ENABLED + value: "true" + - name: DOCSPELL_JOEX_FULL__TEXT__SEARCH_SOLR_URL + value: "http://solr:8983/solr/docspell" + - name: DOCSPELL_JOEX_JDBC_URL + value: "jdbc:postgresql://postgres:5432/dbname" + - name: DOCSPELL_JOEX_JDBC_USER + value: "dbuser" + - name: DOCSPELL_JOEX_ADDONS_EXECUTOR__CONFIG_RUNNER + value: "docker,trivial" + - name: DOCSPELL_JOEX_CONVERT_HTML__CONVERTER + value: "weasyprint" + args: + - "-J-Xmx3G" + resources: + limits: + cpu: '1' + memory: 3Gi + requests: + cpu: '0.5' + memory: 1.5Gi \ No newline at end of file diff --git a/kubernetes/ingress.yaml b/kubernetes/ingress.yaml new file mode 100644 index 00000000..8798bb54 --- /dev/null +++ b/kubernetes/ingress.yaml @@ -0,0 +1,32 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: docspell-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 +spec: + rules: + - host: docspell.example.com + http: + paths: + - path: /restserver(/|$)(.*) + pathType: Prefix + backend: + service: + name: docspell-restserver + port: + name: http + - path: /joex(/|$)(.*) + pathType: Prefix + backend: + service: + name: docspell-joex + port: + name: http + - path: /solr(/|$)(.*) + pathType: Prefix + backend: + service: + name: docspell-solr + port: + name: solr diff --git a/kubernetes/kustomization.yaml b/kubernetes/kustomization.yaml new file mode 100644 index 00000000..82bdc4ea --- /dev/null +++ b/kubernetes/kustomization.yaml @@ -0,0 +1,37 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + name: docspell +namespace: docspell +resources: +- namespace.yaml +- deployment.yaml +- service.yaml +- ingress.yaml +- postgres.yaml +- solr.yaml +configMapGenerator: +- literals: + - DOCSPELL_SERVER_BACKEND_JDBC_USER=dbuser + name: restserver-config +- literals: + - DOCSPELL_JOEX_JDBC_USER=dbuser + name: joex-config +secretGenerator: +- literals: + - DOCSPELL_SERVER_BACKEND_JDBC_PASSWORD=dbpass + - DOCSPELL_SERVER_ADMIN__ENDPOINT_SECRET=admin123 + - DOCSPELL_SERVER_AUTH_SERVER__SECRET=mysecret + - DOCSPELL_SERVER_INTEGRATION__ENDPOINT_HTTP__HEADER_HEADER__VALUE=integration-password123 + - DOCSPELL_SERVER_BACKEND_SIGNUP_NEW__INVITE__PASSWORD=myinvitepass + name: restserver-secrets +- literals: + - DOCSPELL_JOEX_JDBC_PASSWORD=dbpass + name: joex-secrets +images: + - name: docspell/restserver + newTag: latest + - name: docspell/joex + newTag: latest + - name: docspell/dsc + newTag: latest diff --git a/kubernetes/namespace.yaml b/kubernetes/namespace.yaml new file mode 100644 index 00000000..c7bda5e9 --- /dev/null +++ b/kubernetes/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: docspell \ No newline at end of file diff --git a/kubernetes/postgres.yaml b/kubernetes/postgres.yaml new file mode 100644 index 00000000..13d78e72 --- /dev/null +++ b/kubernetes/postgres.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: postgres +spec: + replicas: 1 + serviceName: postgres + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:15.2 + env: + - name: POSTGRES_USER + valueFrom: + configMapKeyRef: + name: restserver-config + key: DOCSPELL_SERVER_BACKEND_JDBC_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: restserver-secrets + key: DOCSPELL_SERVER_BACKEND_JDBC_PASSWORD + - name: POSTGRES_DB + value: dbname + ports: + - name: postgres + containerPort: 5432 + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumeClaimTemplates: + - metadata: + name: postgres-data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + selector: + app: postgres + ports: + - name: postgres + port: 5432 + targetPort: postgres + clusterIP: None \ No newline at end of file diff --git a/kubernetes/secret.yaml b/kubernetes/secret.yaml new file mode 100644 index 00000000..205884c5 --- /dev/null +++ b/kubernetes/secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: docspell-secrets +type: Opaque +stringData: + DOCSPELL_SERVER_ADMIN__ENDPOINT_SECRET: admin123 + DOCSPELL_SERVER_AUTH_SERVER__SECRET: mysecret + DOCSPELL_SERVER_BACKEND_JDBC_PASSWORD: dbpass + DOCSPELL_SERVER_BACKEND_JDBC_USER: dbuser + DOCSPELL_SERVER_BACKEND_SIGNUP_NEW__INVITE__PASSWORD: myinvitepass + DOCSPELL_SERVER_INTEGRATION__ENDPOINT_HTTP__HEADER_HEADER__VALUE: integration-password123 diff --git a/kubernetes/service.yaml b/kubernetes/service.yaml new file mode 100644 index 00000000..5efb775e --- /dev/null +++ b/kubernetes/service.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Service +metadata: + name: restserver +spec: + selector: + app: restserver + ports: + - name: http + protocol: TCP + port: 7880 + targetPort: 7880 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: joex +spec: + selector: + app: joex + ports: + - name: http + protocol: TCP + port: 7878 + targetPort: 7878 + type: ClusterIP diff --git a/kubernetes/solr.yaml b/kubernetes/solr.yaml new file mode 100644 index 00000000..0deef8ac --- /dev/null +++ b/kubernetes/solr.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: solr + labels: + app: solr +spec: + replicas: 1 + serviceName: solr + selector: + matchLabels: + app: solr + template: + metadata: + labels: + app: solr + spec: + containers: + - name: solr + image: solr:9 + ports: + - containerPort: 8983 + command: + - docker-entrypoint.sh + - solr-precreate + - docspell + livenessProbe: # Check for a 302 response + httpGet: + path: /solr/admin/info/system + port: 8983 + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /solr/admin/info/system + port: 8983 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 1 + volumeMounts: + - name: solr-data + mountPath: /var/solr + volumeClaimTemplates: + - metadata: + name: solr-data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: solr +spec: + selector: + app: solr + ports: + - name: solr + port: 8983 + targetPort: 8983