diff --git a/apps/base/hedgedoc/ca.yaml b/apps/base/hedgedoc/ca.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..919958c4d566760f2e4136a00a6cb7546f6f3a19
--- /dev/null
+++ b/apps/base/hedgedoc/ca.yaml
@@ -0,0 +1,26 @@
+---
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: namespace-ca
+  namespace: hedgedoc
+spec:
+  isCA: true
+  commonName: namespace-ca
+  secretName: namespace-ca
+  privateKey:
+    algorithm: ECDSA
+    size: 256
+  issuerRef:
+    name: selfsigned-cluster-issuer
+    kind: ClusterIssuer
+    group: cert-manager.io
+---
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+  name: namespace-ca-issuer
+  namespace: hedgedoc
+spec:
+  ca:
+    secretName: namespace-ca
diff --git a/apps/base/hedgedoc/database.yaml b/apps/base/hedgedoc/database.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c424fdec0fcbb0b196fc86548024bfb5bc84e5b6
--- /dev/null
+++ b/apps/base/hedgedoc/database.yaml
@@ -0,0 +1,18 @@
+apiVersion: "acid.zalan.do/v1"
+kind: postgresql
+metadata:
+  name: hedgedoc-postgres
+  namespace: hedgedoc
+spec:
+  teamId: "hedgedoc"
+  volume:
+    size: 1Gi
+  numberOfInstances: 1
+  users:
+    hedgedoc:
+    - superuser
+    - createdb
+  databases:
+    hedgedoc: hedgedoc
+  postgresql:
+    version: "14"
diff --git a/apps/base/hedgedoc/kustomization.yaml b/apps/base/hedgedoc/kustomization.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..64f890babb79dea7dea60e0669e905b16a4eeea8
--- /dev/null
+++ b/apps/base/hedgedoc/kustomization.yaml
@@ -0,0 +1,15 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: hedgedoc
+resources:
+  - namespace.yaml
+  - ca.yaml
+  - database.yaml
+  - release.yaml
+  - monitoring.yaml
+  - ../../../shared/networkpolicies/allow-from-same-namespace.yaml
+  - ../../../shared/networkpolicies/allow-from-ingress.yaml
+  - ../../../shared/networkpolicies/allow-from-database.yaml
+  - ../../../shared/networkpolicies/allow-from-monitoring.yaml
+patchesStrategicMerge:
+  - networkpolicy.yaml
diff --git a/apps/base/hedgedoc/monitoring.yaml b/apps/base/hedgedoc/monitoring.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4ac0217ac3049d77a84fb1cb9d8837877f2a161c
--- /dev/null
+++ b/apps/base/hedgedoc/monitoring.yaml
@@ -0,0 +1,14 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: hedgedoc
+  namespace: hedgedoc
+spec:
+  endpoints:
+  - honorLabels: true
+    port: http
+  jobLabel: app.kubernetes.io/name
+  selector:
+    matchLabels:
+      app.kubernetes.io/instance: hedgedoc
+      app.kubernetes.io/name: hedgedoc
diff --git a/apps/base/hedgedoc/namespace.yaml b/apps/base/hedgedoc/namespace.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..757afa82b8f83eca40886ebc3b9a27c5b387251c
--- /dev/null
+++ b/apps/base/hedgedoc/namespace.yaml
@@ -0,0 +1,31 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: hedgedoc
+  labels:
+    pod-security.kubernetes.io/audit: restricted
+    pod-security.kubernetes.io/enforce: baseline
+    pod-security.kubernetes.io/warn: restricted
+    pod-security.kubernetes.io/audit-version: v1.23
+    pod-security.kubernetes.io/enforce-version: v1.23
+    pod-security.kubernetes.io/warn-version: v1.23
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: flux-reconciler
+  namespace: hedgedoc
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: flux-reconciler
+  namespace: hedgedoc
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: admin
+subjects:
+  - kind: ServiceAccount
+    name: flux-reconciler
+    namespace: hedgedoc
diff --git a/apps/base/hedgedoc/networkpolicy.yaml b/apps/base/hedgedoc/networkpolicy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e1d0f09a8d8e1202be48d1ca87638221e5c2f173
--- /dev/null
+++ b/apps/base/hedgedoc/networkpolicy.yaml
@@ -0,0 +1,18 @@
+---
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  name: allow-from-ingress
+spec:
+  podSelector:
+    matchLabels:
+      app.kubernetes.io/name: hedgedoc
+---
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  name: allow-from-monitoring
+spec:
+  podSelector:
+    matchLabels:
+      app.kubernetes.io/name: hedgedoc
diff --git a/apps/base/hedgedoc/release.yaml b/apps/base/hedgedoc/release.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..192708f2215803ccf2722780d0dcc879637bc053
--- /dev/null
+++ b/apps/base/hedgedoc/release.yaml
@@ -0,0 +1,65 @@
+apiVersion: helm.toolkit.fluxcd.io/v2beta1
+kind: HelmRelease
+metadata:
+  name: hedgedoc
+  namespace: hedgedoc
+spec:
+  serviceAccountName: flux-reconciler
+  timeout: 5m
+  releaseName: hedgedoc
+  chart:
+    spec:
+      chart: ./charts/hedgedoc
+      sourceRef:
+        kind: GitRepository
+        name: flux-system
+        namespace: flux-system
+  interval: 5m
+  valuesFrom:
+    - kind: ConfigMap
+      name: hedgedoc-base-values
+      valuesKey: values.yaml
+    - kind: Secret
+      name: hedgedoc-override-values
+      valuesKey: values-overrides.yaml
+      optional: true
+    - kind: Secret
+      name: hedgedoc.hedgedoc-postgres.credentials.postgresql.acid.zalan.do
+      valuesKey: username
+      targetPath: postgresql.auth.username
+      optional: false
+    - kind: Secret
+      name: hedgedoc.hedgedoc-postgres.credentials.postgresql.acid.zalan.do
+      valuesKey: password
+      targetPath: postgresql.auth.password
+      optional: false
+  install:
+    remediation:
+      retries: -1
+  upgrade:
+    remediation:
+      retries: -1
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: hedgedoc-base-values
+  namespace: hedgedoc
+data:
+  values.yaml: |
+    postgresql:
+      enabled: true
+      postgresqlHostname: hedgedoc-postgres.hedgedoc.svc.cluster.local
+      auth:
+        database: hedgedoc
+    resources:
+      limits:
+        cpu: "1"
+        memory: 512Mi
+      requests:
+        cpu: 100m
+        memory: 512Mi
+    podSecurityContext:
+      runAsUser: "10000"
+      runAsGroup: "10000"
+      runAsNonRoot: true
diff --git a/apps/k8s01/hedgedoc/certificate.yaml b/apps/k8s01/hedgedoc/certificate.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..14b9590c7d5c40fcf37820d5777cb253e41d677a
--- /dev/null
+++ b/apps/k8s01/hedgedoc/certificate.yaml
@@ -0,0 +1,64 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+    name: hedgedoc-tls
+    namespace: hedgedoc
+spec:
+    dnsNames:
+        - ENC[AES256_GCM,data:lCKhFI5WZgGsMkzhfxTJ2M8eQ+Jddd0=,iv:WVw1UFH0x2v7II9bZY1nZt07rtkcP161Tk9XVWma528=,tag:44WbQUbBtjAK1RwU8gKuug==,type:str]
+    issuerRef:
+        name: letsencrypt
+        kind: ClusterIssuer
+    secretName: ingress-hedgedoc-tls
+sops:
+    kms: []
+    gcp_kms: []
+    azure_kv: []
+    hc_vault: []
+    age: []
+    lastmodified: "2023-04-23T22:42:19Z"
+    mac: ENC[AES256_GCM,data:mEp73QGrUnBahXkrM5UPMtGbGDRl3LE4drZs56T81xpf4jqiqI8cIvGwZIJxqTsZcJT0vNbgxz2IulTgizyM1O5p24+Z3ZzrDZ05Zhgbu9HNZ0CSaOpfHZDEJuIUm5TQwsvlh89F7pNErXu3d3dxrLtuU6kX87ywZoWPpvd2k3w=,iv:ASRDctACn+PH49Xqb7O7FXK9Pg36BHqHX8A5/01Vubk=,tag:DALMxmcxUs6nYgmTXPOThw==,type:str]
+    pgp:
+        - created_at: "2022-01-21T18:13:48Z"
+          enc: |-
+            -----BEGIN PGP MESSAGE-----
+
+            wcFMA7kpg2bgzVHcARAAHhDshl1OJqNRUolNvbIXzOuDzssJnvyi6cIZuMmVMsxf
+            a6wAWAtYOehvtn1ODL7/h4fIpBtfp7d8VuwfJSrh3ghUeiOl3zRzQbmaFA2L5/iG
+            Jd94tFAVwIl30qjcYqGVB2RF27VF1RElzgDLQh3hiXn1hDC+WmNSnBF5hwnwCFOL
+            wM4BHuE2AB4TX3PlYSo1n71VSzcCqRzbIxelZasYLnJQVL0VE6AjEd/fHS468R8N
+            aZ3mhmHW3sWzuLHNREMD2Q3ghkguLhau0VoETlYRI9103I4k7/khFrhAj5l2/PUr
+            2SWgpXyRqXVaKPeTiQs3QR8B5jNq3BlZj6Celw5Ig/wx3LY0EhI9e9WFgtSlZxM+
+            2yk65HQGvTIgsbys/z/0skA9vqik9csFRsH9iK42E/+XLvoAT6yxyl0cv1kBEyAS
+            ggPmKOq8+CT+voHzuh8kZHq9Sa8kH5xL1DQLzX2yIruV3OhTPSK+VlDpjUbycmI2
+            qR1oCo/snOJwwwvfl9vu0B8FCwhrz8554ZQBErFfJl6GFiUV8LElRlZh5S9Jiysr
+            nYJS5gxrcvjF/0Y6EHEfWDRDxvCHoWQpWhl2hRkh5UlQKH0ab+QWLYpISyNJxjfl
+            orQJdaVX3BQwhqMLwiMLGoaNGrSpmxXveLOZmsdK0obXC67lyE6ZM/Wy6gx2dFnS
+            5gFdXCLzQmmjYK8gIlsejQdnxZI2qWavZIN9T70OZQGaDE/S+U1uxKjuGBM7HTcP
+            7f1nUa6z96A9ydWs1xHjtm7k172V16PMSrvjQ8KLhFJd9eJDq3ksAA==
+            =XgF6
+            -----END PGP MESSAGE-----
+          fp: 286791FB6648539775DB31B8FCB98C2A3EC6F601
+        - created_at: "2022-01-21T18:13:48Z"
+          enc: |
+            -----BEGIN PGP MESSAGE-----
+
+            hQIMA4oYbIHZIrAPAQ//S/9rOkbd3beNH20dxgZ7VuZxgnjiV3Hd3om717njcMm2
+            kCfTJ3AmpLtQsT2s1W221tIyCwtHOobj82ANP9KzNi4e6v3LlNTIVHTQiHXk9KJP
+            AX6JoCOLu3bAI0xcdApNBU2wAlHBVC+T4BUfhPqD5AdHpW++e1qUIsM/6TViunHj
+            BWoIA0bpXqyOhTm1GbkJrHMgczJn2qgR5lBf8wgGmASd8jlNyfA7SxoKHj8sl/Ji
+            nucP/90dmyD2eBIJYdYS3anJYa2uP96oioG5xxIyfppnL5dwozDAit3Z5vvnBZNb
+            1rrpUnN8H0cCcaj7tmDEmjGfjGwxLKegQRZX7Pg5hwaaOOPGheXf8Ip/DpDf6T0n
+            Sq24X6DC5gD1RBU+YY6ZayMt/OKpVVVwRlY4BTDIUe4M+ecK/fve5vpDW2M+KWMc
+            pOkO1B09/prsX0w5XjFh8hb/6HlDDhomiB+BszcRCUDzocRzSEIFwMf7/iTaExe8
+            2fKCCHB4kHo6GHpydlQOpnGMOvDmiNKopXxTkFQUFQjyRmHGXf/u79JNXBjHkniv
+            ZiokjTEarwMp68dyiaL4L/5Uk+4NG3MetobqSaeW2TbeBwif3G2eFleYscz7QPIR
+            5ZBBhU/CoUEz2Xge6t8rlp8PNcQ1yq/R+tZjaeqIIT4++ZxCErhA0lsxyFrgLefU
+            aAEJAhD7hR3IMDGN2zOZSiw1IBz9P8Jss/oERQiuVpe/eTv5Vqj9vuL+koKftwnF
+            vSVkNo0fLwNLtnU659Mkoj9utoUL9tAhcCMpP3NehKkBG5RjF9crnIP6zT3lvVU0
+            GYyW4Lsfrt/a
+            =FfV+
+            -----END PGP MESSAGE-----
+          fp: B137EE1549DFAF960DD1E2B15147025FB9F09E07
+    encrypted_regex: ^(data|stringData|email|dnsZones?|dnsNames?|hosts?|tang|externalURL)$
+    version: 3.7.3
diff --git a/apps/k8s01/hedgedoc/database-override.yaml b/apps/k8s01/hedgedoc/database-override.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c6e573cc2083df72d114eb7a9575c50ba7ad7155
--- /dev/null
+++ b/apps/k8s01/hedgedoc/database-override.yaml
@@ -0,0 +1,9 @@
+apiVersion: "acid.zalan.do/v1"
+kind: postgresql
+metadata:
+  name: hedgedoc-postgres
+  namespace: hedgedoc
+spec:
+  numberOfInstances: 2
+  volume:
+    size: 5Gi
diff --git a/apps/k8s01/hedgedoc/hedgedoc-values.yaml b/apps/k8s01/hedgedoc/hedgedoc-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6a5adbeda47b592c77c882be28854efffcabe754
--- /dev/null
+++ b/apps/k8s01/hedgedoc/hedgedoc-values.yaml
@@ -0,0 +1,60 @@
+apiVersion: v1
+kind: Secret
+metadata:
+    name: hedgedoc-override-values
+    namespace: hedgedoc
+type: Opaque
+stringData:
+    values-overrides.yaml: ENC[AES256_GCM,data:pFsh2X6nivnIPPrkFk9juoVenBnF1scm003iHsZmrNw+1bQW8uNZWLBEAtYC/fJ/B9B5SnQ0+Ja50P8MfuXMkxad4+4Sawbu4dJ5qK1oCEEjy9ol8lqPlgZjE07g67jMo11A9Doo80BJLElWpZQWRyhtnywGgZTrBCBCLukZbSnAm0hwpKJ5dckDVmL8A/kfufRxEFcfundPf9rk6xFUH2frBAil5tZqfYd3CSgVZHA1MHH9stOW4tN08UXCoyHGdP4ZHpFj/ChRZ99KyapetF5vItj8CMvWmvaRmkMLc5i3hkLiWF0Zfrp4qFL9F1KQhmXX0m0C9i4QHLW1QN2tXiS8WccxuMhxHLFW0TMcKdSvolZDioyObUMwAAyoGTE1BAwBb18Vtk8O9GXC0TKy0Df53XRoJh89r914D5fRlmUTqbdqW9bTdoJApYMmdhva0PrNJknmcjjAkCH0FN2iwV0N3MuXChXulYxd4ye24IvQGOh2Hen+IjxCbkFY5tpbQoQ4C9wzoD183LL1oepNYLUkOA4v5x1dUf8OxaGNQdfn6LIMXxnaFKrSrdOJxgY7fwIrhqjOinu4vlIXguiMtY4WTQXjjccTg23zT1HD8z17LmyfANjXH2ljA4jH4fky1SzizspRADKpc7k6nqyiAl6BHBDJFJrdwQ3ERJYiEKnOlef/jv9bncfcP6R776mCCnlwmjM4Pgt/FytWn3i09jviRIRQ25u6Jxv3TM8m2/k2pOBr9sc0P+M94xvR2J3gvSm3xTqEFhQcSswjjCQ5M97sCqBkbT+CacY0CpyawTSbFeeBngBU0bh/aXsghFmcc0KawvkSzZwTTSvQL495kfuL8i07Agh8ZAuk7PPx37JabRVJ8CMIYs6kOQfRsTG0c1yzgboFcsH2dlAVN9GhdI+A2E3WAvk6dPrfpDwZqYgzkdntWVW92fkj2lulxazxnrSdLuu76eQTtPbGMjePjOD3NgLS9hwdFd/A/iAkQ5pJqCUXa25gZYxYm7ji4hUw+t2eJedmlErLQPIZcophAPkj8a3tx5BGIuj2ehtqMVdSVWhBBRiVgWquOT/I7cj22cksdOwRtNLyyVaxb++fy3mKI3JVICFgPaUcfpfH1ByhcAUbCduzzIOMykUb5lhIvqmqzZ6OZjA3rG7LqnMTU7iPqezgu4uNd/Lcuy9+MMCMH5J1bhA8bffCDyg+r6Cd2rEpU7eczOZoo+Q2lnVLWmgxj8KLJZ7VxU5C5ItMeOkuljTpQzXyDKeQ61HlU0tTZKiMBbM9hq2V9LmgQwkwBqBNcDf+6Z6w+meH77mLUXDPIyE4X11wWmrH4+tT5V1R+014hZwuC3Zpm+fUH/STMiAz10m1mCQvgaMZ9ZqwarutLHl2Yno+QyduchwiAgDlYEL8aoWMqmfWVSp2fuPYvuxOG5AxUjiJ8ZCc+OZHrS3zj8ysrWElj+f7qgeYbINbIQ2ctpV/yrYOxuOKqzxsHJ26zwWYhAvO7goPztPT4ZU58oj+IA1l7EaYdiy5tK7UvSHPxnNUQINdTT7AsHi1xwsVL+TyHAbSRZ4mZNARn4mr9BHC41+xgZfNrY48L5McYUSZAXPbN3HcvXi821cVc9o0pXf1X8yE36PSZY45iKTsG5tHcqxfXHAm62aBngKmwrl6D3BaDq8iauX4k/PMyVgq6qt0r247MAlcvu1nwgFfdugHLPNitmbIyZOTCk9nl84dQX1Ps5Rabr5ZQitB1sSd9mPttX6HvbIsTzRHxTIKUW/KHHtIpR99YwK50w+czKrnTBlmw/soTunzdVByso88mAB94+ebIlFhtYVHz6myGxI/GqJFbFep/NYdWtLvclAttr7TIlPdQljQXyZ8Y7MBOXQu5IGyNdxv0k+/,iv:3w5d5fXhEeXUjTCU8TFnA0EzdEo8p7VtqxuR5HL8tSo=,tag:FZFOjEx3HPPtfqx+zc4gNw==,type:str]
+sops:
+    kms: []
+    gcp_kms: []
+    azure_kv: []
+    hc_vault: []
+    age: []
+    lastmodified: "2023-04-23T23:14:45Z"
+    mac: ENC[AES256_GCM,data:M5EVgZy0v2QGRlggG3HoQjoo8PrzG3iLv+TySSYg75cyUXY5aYUL1QyetU/A0vilvbOq7oxH74K51QG/KkIFY7IRqAfaDqj69Cs1GV2YUqOtQxkLz3H7dm9X6nXGtDEmIj/J7PM1uYw5CTJt+JaxHytYDkhPSld5aakRb9qffMw=,iv:+HXfFQHw0PzSR2P0uE8mKSnjPWFg5bFK77tvB8MtWnE=,tag:OZlPDi4DOFjoJRQgPd0nXQ==,type:str]
+    pgp:
+        - created_at: "2022-03-22T22:26:35Z"
+          enc: |-
+            -----BEGIN PGP MESSAGE-----
+
+            wcFMA7kpg2bgzVHcARAApcdDAfEgx93xGtkm4f7xTuRhvUyl8lw85rIHbWcAveYU
+            ayU88OLaoQyeZDZkOXbtxMHpry8GbId6vPAJ7KflT2eMP0A4uQGSSCQO6+5QcaYg
+            sbO/zT4vdprN7icLbvmmoK2Dh+hOo5Z7/7YGmdJfaaATzT2BGL/cVS1bonI83vXR
+            lzlW/DglIe7oNEKGVT5vWR5uGvq/dJwSRe/34eutEnJuV30imxHOcpxy3uXJFFXJ
+            3eKTk8dNLz3UE3IeUjbFdPFZYU+grOAOOCZRK0IOYFn+SF7E3dewgiwEdaXzz3gK
+            /6aEMEmf5vyVqn9jOaqZhKRqE7tW5HnhwIIlxcMPhkLVZvYf4F2EDA5f12C2hdp0
+            s7fFhU7v5GgFaHMJuaWVPxDnWTrNIst9bgeJv/N4RVfrLifrZJcqa9lE8ou0iCr5
+            dLi9d6UjsgWAREIViz+Uz7dJQ9QeJ6PGYgg/xgf0ihJFG7sx+TBG58DKb3G3tyUV
+            8hfK8Ou9m+zYnd13mJ2mV3rY0rmXusT+NcqTG2G4bBG5NimGpJS3rO7tAjjp/8sN
+            hMM46ay0vVTUXx1FwmjUFDG1e4sc7fKxTaCBizMjeUfZpAOiy/10YQmrFHBsftpo
+            K5j0nFMoG9NeO+2ffEmLhRtxvMe3WpINk7du3F624rYIGCB0aNUP69FCeJKuUQHS
+            5gH5AwnxOAtQakDksfLxJhUG1NlaS0iAFkZkTTibvOJwsY9L/scDDQlseb5zBKaZ
+            sOPwmn6hL4KavxF9BPG33ILkZKbkcvlaTlAMMY3iBs+MZeIB4+i/AA==
+            =SQqg
+            -----END PGP MESSAGE-----
+          fp: 286791FB6648539775DB31B8FCB98C2A3EC6F601
+        - created_at: "2022-03-22T22:26:35Z"
+          enc: |
+            -----BEGIN PGP MESSAGE-----
+
+            hQIMA4oYbIHZIrAPAQ//fGGoDT5KfsG/o6r5xhDHSc0IFH6zT2TFIB6TuA5SwHfV
+            8t3IeKD0bE//4f8AxGAVocw+AetolwrQL/Tl+n0UV9P44Jeh5VlCAGltHcowR53o
+            zdjS3+i9K3OOvQFhF+aYrPcnc+aTn9KbptHCam0w+Lr2UkYSAPAZHsBcoMp24mHX
+            6A+5kP1kaRzFzEn4TCNeTt13W1AsJIoSagkBWfYRBkRPk1OzGOuYqX6yeqj7a0kM
+            8uiloTQgWOiBSOyRtxUJi87CTrMXyb0F2E9HMyhgRnzF0YX0ZU0UVG8MNdRL8eFD
+            WYY68OK7DQw3zlJubscYQ2jltxKcq5g9qUCw/sXaNurtohIx9UeaHtfp036EMb22
+            5StgGEnBirUzfSrQGT3kuj20lcMtQAr/d1UsmQNjB36eOZSrx0m80pO8JVYL62/O
+            HLYnAHU52aAPtE7brNEVg4yRLCbWyVY3Z3H9OaTVXwNIMFoMEgkHHnNlsb+1ZnhV
+            cStKMO3H6W8eXQi3VGIVNhuC1ltsxHQL1I22Kr41JEnuaB9Jy5bsEbrO4XGyDdte
+            hMI8Gx+0KZAMlKuZKLS6sMa4oVnQTy8w20PtVrrS0zDrQRPpxBrOgzjrNeMj9FpS
+            q/efiCAOBc8eVd8N/7j66UItwrysfmIfsHWfoPotS7F6WmUHeAyoWjfcvTZyd4bU
+            ZgEJAhAtdCnHNvUSl5O9XZuSu51pRwj+O72kZXRSJWv7GTT9dsRfuM5Dy9A/tuVI
+            BuZraI4JyAWb2KbkM6onp3Rh9IcLuzqEYm/ETktxTtO1HlcVPJ2NMcFgTCzaIGX9
+            +rtkG7tPbA==
+            =tvBa
+            -----END PGP MESSAGE-----
+          fp: B137EE1549DFAF960DD1E2B15147025FB9F09E07
+    encrypted_regex: ^(data|stringData|email|dnsZones?|dnsNames?|hosts?|tang|externalURL|.*-secret|.*-url|.*Secrets?|.*-domain|password|subjects|node|apiURL|.*(S|s)erverNames?|.*SecretKey)$
+    version: 3.7.3
diff --git a/apps/k8s01/hedgedoc/kustomization.yaml b/apps/k8s01/hedgedoc/kustomization.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..587ab8c3e2860da91292673d504aba9882df15e6
--- /dev/null
+++ b/apps/k8s01/hedgedoc/kustomization.yaml
@@ -0,0 +1,11 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: hedgedoc
+resources:
+  - ../../base/hedgedoc
+  - certificate.yaml
+  - hedgedoc-values.yaml
+  - slo.yaml
+  - ../../../shared/resourcequotas/default.yaml
+patchesStrategicMerge:
+  - database-override.yaml
diff --git a/apps/k8s01/hedgedoc/slo.yaml b/apps/k8s01/hedgedoc/slo.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..bbd016a349800dd52a0784e15a25f25f069f2569
--- /dev/null
+++ b/apps/k8s01/hedgedoc/slo.yaml
@@ -0,0 +1,21 @@
+apiVersion: sloth.slok.dev/v1
+kind: PrometheusServiceLevel
+metadata:
+  name: requests-hedgedoc
+  namespace: hedgedoc
+spec:
+  service: "hedgedoc"
+  slos:
+    - name: "requests-availability"
+      objective: 98
+      description: "Hedgedoc SLO based on availability for HTTP request responses."
+      sli:
+        events:
+          errorQuery: sum(rate(nginx_ingress_controller_requests{exported_namespace="nextcloud",ingress="nextcloud",status=~"(5..|429)"}[{{.window}}]))
+          totalQuery: sum(rate(nginx_ingress_controller_requests{exported_namespace="nextcloud",ingress="nextcloud"}[{{.window}}])) > 0 OR vector(1)
+      alerting:
+        name: NextcloudHighErrorRate
+        labels:
+          category: "availability"
+        annotations:
+          summary: "High error rate on 'nextcloud' requests responses"
diff --git a/charts/hedgedoc/.helmignore b/charts/hedgedoc/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778
--- /dev/null
+++ b/charts/hedgedoc/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/charts/hedgedoc/Chart.lock b/charts/hedgedoc/Chart.lock
new file mode 100644
index 0000000000000000000000000000000000000000..f3c7009f622bd49ce638412097323d00a4003c96
--- /dev/null
+++ b/charts/hedgedoc/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: postgresql
+  repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami
+  version: 11.9.13
+digest: sha256:00f9aa4e28ee58f51a9c56fe6d07219babc24ae34571815e64b388f094c4de9e
+generated: "2023-03-19T19:38:00.244092372Z"
diff --git a/charts/hedgedoc/Chart.yaml b/charts/hedgedoc/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4d6639e8859708e2fea1776fa5d0c560d4d14a86
--- /dev/null
+++ b/charts/hedgedoc/Chart.yaml
@@ -0,0 +1,24 @@
+apiVersion: v2
+name: hedgedoc
+description: A platform to write and share markdown.
+home: https://hedgedoc.org
+icon: https://avatars.githubusercontent.com/u/67865462
+type: application
+keywords:
+    - hedgedoc
+    - markdown
+    - collaboration
+sources:
+    - https://github.com/hedgedoc/hedgedoc/tree/master
+    - https://git.shivering-isles.com/shivering-isles/infrastructure-gitops/-/tree/main/charts/hedgedoc
+version: 0.1.0
+# renovate: image=quay.io/hedgedoc/hedgedoc
+appVersion: 1.9.7
+maintainers:
+- name: Sheogorath
+  url: https://shivering-isles.com
+dependencies:
+  - name: postgresql
+    version: 11.9.13
+    repository: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami
+    condition: postgresql.enabled
\ No newline at end of file
diff --git a/charts/hedgedoc/charts/postgresql-11.9.13.tgz b/charts/hedgedoc/charts/postgresql-11.9.13.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..2d3ac623a5860d4fcc1255afb5c9ca7c4d9d05e1
Binary files /dev/null and b/charts/hedgedoc/charts/postgresql-11.9.13.tgz differ
diff --git a/charts/hedgedoc/templates/NOTES.txt b/charts/hedgedoc/templates/NOTES.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0f1572f960b407c0170a26bef28e838a531984a8
--- /dev/null
+++ b/charts/hedgedoc/templates/NOTES.txt
@@ -0,0 +1,22 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+  {{- range .paths }}
+  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+  {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "hedgedoc.fullname" . }})
+  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+  echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+           You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "hedgedoc.fullname" . }}'
+  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "hedgedoc.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+  echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "hedgedoc.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+  export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+  echo "Visit http://127.0.0.1:8080 to use your application"
+  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/charts/hedgedoc/templates/_helpers.tpl b/charts/hedgedoc/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..f2c532d115fd8e031d97fd728645e3d9049d380c
--- /dev/null
+++ b/charts/hedgedoc/templates/_helpers.tpl
@@ -0,0 +1,79 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "hedgedoc.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "hedgedoc.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "hedgedoc.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "hedgedoc.labels" -}}
+helm.sh/chart: {{ include "hedgedoc.chart" . }}
+{{ include "hedgedoc.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "hedgedoc.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "hedgedoc.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "hedgedoc.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "hedgedoc.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
+
+{{/*
+Get the postgresql secret.
+*/}}
+{{- define "hedgedoc.postgresql.secretName" -}}
+{{- if (and (or .Values.postgresql.enabled .Values.postgresql.postgresqlHostname) .Values.postgresql.auth.existingSecret) }}
+    {{- printf "%s" (tpl .Values.postgresql.auth.existingSecret $) -}}
+{{- else if .Values.postgresql.enabled -}}
+    {{- printf "%s-postgresql" (tpl .Release.Name $) -}}
+{{- else -}}
+    {{- printf "%s" (include "common.names.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{- define "hedgedoc.postgresql.fullname" -}}
+{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
\ No newline at end of file
diff --git a/charts/hedgedoc/templates/configmap.yaml b/charts/hedgedoc/templates/configmap.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..04fd4de87e7fee80276b7b85aec2bb7fdc6c29c6
--- /dev/null
+++ b/charts/hedgedoc/templates/configmap.yaml
@@ -0,0 +1,81 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "hedgedoc.fullname" . }}
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+data:
+  {{- if .Values.postgresql.enabled }}
+  CMD_DB_HOST: {{ template "hedgedoc.postgresql.fullname" . }}
+  CMD_DB_PORT: "5432"
+  {{- else }}
+  CMD_DB_HOST: {{ .Values.postgresql.postgresqlHostname }}
+  CMD_DB_PORT: {{ .Values.postgresql.postgresqlPort | default "5432" | quote }}
+  {{- end }}
+  CMD_DB_DATABASE: {{ .Values.postgresql.auth.database }}
+  CMD_DB_USERNAME: {{ .Values.postgresql.auth.username }}
+  {{- with .Values.config.session.lifeTime }}
+  CMD_SESSION_LIFE: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.allowFreeUrl }}
+  CMD_ALLOW_FREE_URL: {{ . | quote }}
+  {{- end }}
+  {{- if .Values.ingress.enabled }}
+  CMD_DOMAIN: {{ (index .Values.ingress.hosts 0).host | quote }}
+  {{- else }}
+  {{- with .Values.config.domain }}
+  CMD_DOMAIN: {{ . | quote }}
+  {{- end }}
+  {{- end }}
+  {{- with .Values.config.email }}
+  CMD_EMAIL: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.protocolUseSsl }}
+  CMD_PROTOCOL_USESSL: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.urlAddPort }}
+  CMD_URL_ADDPORT: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.useCdn }}
+  CMD_USECDN: {{ . | quote }}
+  {{- end }}
+  CMD_IMAGE_UPLOAD_TYPE: minio
+  {{- with .Values.config.minio.endpoint }}
+  CMD_MINIO_ENDPOINT: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.minio.port }}
+  CMD_MINIO_PORT: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.minio.secure }}
+  CMD_MINIO_SECURE: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.s3bucket }}
+  CMD_S3_BUCKET: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.authorisationUrl }}
+  CMD_OAUTH2_AUTHORIZATION_URL: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.tokenUrl }}
+  CMD_OAUTH2_TOKEN_URL: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.userProfileUrl }}
+  CMD_OAUTH2_USER_PROFILE_URL: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.userProfileUsername }}
+  CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.userProfileDisplayName }}
+  CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.userProfileEmailAttr }}
+  CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.providerName }}
+  CMD_OAUTH2_PROVIDERNAME: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.scope }}
+  CMD_OAUTH2_SCOPE: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.defaultPermission }}
+  CMD_DEFAULT_PERMISSION: {{ . | quote }}
+  {{- end }}
\ No newline at end of file
diff --git a/charts/hedgedoc/templates/deployment.yaml b/charts/hedgedoc/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4e926e5a679e1a9802b2d858e68d5c81d0756f67
--- /dev/null
+++ b/charts/hedgedoc/templates/deployment.yaml
@@ -0,0 +1,70 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "hedgedoc.fullname" . }}
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+spec:
+  replicas: 1
+  strategy:
+    type: Recreate
+  selector:
+    matchLabels:
+      {{- include "hedgedoc.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      {{- with .Values.podAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      labels:
+        {{- include "hedgedoc.selectorLabels" . | nindent 8 }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      serviceAccountName: {{ include "hedgedoc.serviceAccountName" . }}
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      containers:
+        - name: {{ .Chart.Name }}
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          envFrom:
+            - configMapRef:
+                name: {{ include "hedgedoc.fullname" . }}
+          env:
+            - name: "CMD_DB_PASSWORD"
+              valueFrom:
+                secretKeyRef:
+                  name: {{ template "hedgedoc.postgresql.secretName" . }}
+                  key: password
+          ports:
+            - name: http
+              containerPort: 3000
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              path: /_health
+              port: http
+          readinessProbe:
+            httpGet:
+              path: /_health
+              port: http
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
diff --git a/charts/hedgedoc/templates/ingress.yaml b/charts/hedgedoc/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..719ad3640f9affc9d1bc540e4d2cea5a008b09c5
--- /dev/null
+++ b/charts/hedgedoc/templates/ingress.yaml
@@ -0,0 +1,61 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "hedgedoc.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
+  {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
+  {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
+  {{- end }}
+{{- end }}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+  name: {{ $fullName }}
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+  {{- with .Values.ingress.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+  {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
+  ingressClassName: {{ .Values.ingress.className }}
+  {{- end }}
+  {{- if .Values.ingress.tls }}
+  tls:
+    {{- range .Values.ingress.tls }}
+    - hosts:
+        {{- range .hosts }}
+        - {{ . | quote }}
+        {{- end }}
+      secretName: {{ .secretName }}
+    {{- end }}
+  {{- end }}
+  rules:
+    {{- range .Values.ingress.hosts }}
+    - host: {{ .host | quote }}
+      http:
+        paths:
+          {{- range .paths }}
+          - path: {{ .path }}
+            {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
+            pathType: {{ .pathType }}
+            {{- end }}
+            backend:
+              {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
+              service:
+                name: {{ $fullName }}
+                port:
+                  number: {{ $svcPort }}
+              {{- else }}
+              serviceName: {{ $fullName }}
+              servicePort: {{ $svcPort }}
+              {{- end }}
+          {{- end }}
+    {{- end }}
+{{- end }}
diff --git a/charts/hedgedoc/templates/secret.yaml b/charts/hedgedoc/templates/secret.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..19d8837bde2d7a38f7c30c9a4cf2e9d705954279
--- /dev/null
+++ b/charts/hedgedoc/templates/secret.yaml
@@ -0,0 +1,26 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: dotfile-secret
+data:
+  {{- with .Values.config.session.secret }}
+  CMD_SESSION_SECRET: {{ . | b64enc }}
+  {{- end }}
+  {{- with .Values.config.github.clientId }}
+  CMD_GITHUB_CLIENTID: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.github.clientSecret }}
+  CMD_GITHUB_CLIENTSECRET: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.minio.accessKey }}
+  CMD_MINIO_ACCESS_KEY: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.minio.secretKey }}
+  CMD_MINIO_SECRET_KEY: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.clientId }}
+  CMD_OAUTH2_CLIENT_ID: {{ . | quote }}
+  {{- end }}
+  {{- with .Values.config.oauth.clientSecret }}
+  CMD_OAUTH2_CLIENT_SECRET: {{ . | quote }}
+  {{- end }}
\ No newline at end of file
diff --git a/charts/hedgedoc/templates/service.yaml b/charts/hedgedoc/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..92a1bfb79e72a770f899f9e994b3388e19e53481
--- /dev/null
+++ b/charts/hedgedoc/templates/service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "hedgedoc.fullname" . }}
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.service.type }}
+  ports:
+    - port: {{ .Values.service.port }}
+      targetPort: http
+      protocol: TCP
+      name: http
+  selector:
+    {{- include "hedgedoc.selectorLabels" . | nindent 4 }}
diff --git a/charts/hedgedoc/templates/serviceaccount.yaml b/charts/hedgedoc/templates/serviceaccount.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7dfb0ed66af28195e688548ea74a7adbbee79a2e
--- /dev/null
+++ b/charts/hedgedoc/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "hedgedoc.serviceAccountName" . }}
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+  {{- with .Values.serviceAccount.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- end }}
diff --git a/charts/hedgedoc/templates/tests/test-connection.yaml b/charts/hedgedoc/templates/tests/test-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..99f9ed6aaa4f36d3b83f3a79001529cc0732edf7
--- /dev/null
+++ b/charts/hedgedoc/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ include "hedgedoc.fullname" . }}-test-connection"
+  labels:
+    {{- include "hedgedoc.labels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args: ['{{ include "hedgedoc.fullname" . }}:{{ .Values.service.port }}']
+  restartPolicy: Never
diff --git a/charts/hedgedoc/tests/80_subchart_postgresql_test.yaml b/charts/hedgedoc/tests/80_subchart_postgresql_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fae99ccc1f7c3c3627fd83f5c53f45d12173adc9
--- /dev/null
+++ b/charts/hedgedoc/tests/80_subchart_postgresql_test.yaml
@@ -0,0 +1,111 @@
+suite: postgresql
+templates:
+  - charts/postgresql/templates/primary/svc.yaml
+  - charts/postgresql/templates/secrets.yaml
+  - charts/postgresql/templates/primary/statefulset.yaml
+  - configmap.yaml
+  - deployment.yaml
+  - secret.yaml
+values:
+  - mocks/test.yaml
+chart:
+  version: 1.2.3
+  appVersion: 4.5.6
+tests:
+  - it: should match service name and configured host
+    asserts:
+      - equal:
+          path: metadata.name
+          value: RELEASE-NAME-postgresql
+        template: charts/postgresql/templates/primary/svc.yaml
+      - equal:
+          path: data.CMD_DB_HOST
+          value: RELEASE-NAME-postgresql
+        template: configmap.yaml
+  - it: should match password secret names and structure
+    asserts:
+      - isNotEmpty:
+          path: data.password
+        template: charts/postgresql/templates/secrets.yaml
+        documentIndex: 0
+      - equal:
+          path: metadata.name
+          value: RELEASE-NAME-postgresql
+        template: charts/postgresql/templates/secrets.yaml
+        documentIndex: 0
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: "CMD_DB_PASSWORD"
+            valueFrom:
+              secretKeyRef:
+                name: RELEASE-NAME-postgresql
+                key: password
+        template: deployment.yaml
+  - it: should have correct default the database username
+    asserts:
+      - equal:
+          path: data.CMD_DB_USERNAME
+          value: hedgedoc
+        template: configmap.yaml
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: POSTGRES_USER
+            value: "hedgedoc"
+        template: charts/postgresql/templates/primary/statefulset.yaml
+  - it: should allow to change the database username
+    set:
+      postgresql:
+        auth:
+          username: test
+    asserts:
+      - equal:
+          path: data.CMD_DB_USERNAME
+          value: test
+        template: configmap.yaml
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: POSTGRES_USER
+            value: "test"
+        template: charts/postgresql/templates/primary/statefulset.yaml
+  - it: should allow to control password changes
+    set:
+      postgresql:
+        auth:
+          password: test
+    asserts:
+      - equal:
+          path: data.password
+          value: dGVzdA==
+        template: charts/postgresql/templates/secrets.yaml
+        documentIndex: 0
+  - it: should use the expected database name
+    asserts:
+      - equal:
+          path: data.CMD_DB_DATABASE
+          value: hedgedoc
+        template: configmap.yaml
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: POSTGRES_DB
+            value: "hedgedoc"
+        template: charts/postgresql/templates/primary/statefulset.yaml
+  - it: should allow to change the database name
+    set:
+      postgresql:
+        auth:
+          database: test
+    asserts:
+      - equal:
+          path: data.CMD_DB_DATABASE
+          value: test
+        template: configmap.yaml
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: POSTGRES_DB
+            value: "test"
+        template: charts/postgresql/templates/primary/statefulset.yaml
\ No newline at end of file
diff --git a/charts/hedgedoc/tests/98_snapshot_test.yaml b/charts/hedgedoc/tests/98_snapshot_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..eb71eb5a08c208aa9423b7b8e831978dc58c8c79
--- /dev/null
+++ b/charts/hedgedoc/tests/98_snapshot_test.yaml
@@ -0,0 +1,24 @@
+suite: Basic Snapshot test
+templates:
+  - configmap.yaml
+  - deployment.yaml
+  - ingress.yaml
+  - secret.yaml
+  - service.yaml
+  - serviceaccount.yaml
+values:
+  - mocks/test.yaml
+tests:
+  - it: should match basic snapshot
+    set:
+      mastodon:
+        createAdmin:
+          enabled: true
+    chart:
+      version: 1.2.3
+      appVersion: 4.5.6
+    capabilities:
+      apiVersions:
+        - networking.k8s.io/v1/Ingress
+    asserts:
+      - matchSnapshot: {}
diff --git a/charts/hedgedoc/tests/__snapshot__/98_snapshot_test.yaml.snap b/charts/hedgedoc/tests/__snapshot__/98_snapshot_test.yaml.snap
new file mode 100644
index 0000000000000000000000000000000000000000..9ad622dee1f5dff8ab2d8c45cd8225df8719f4cd
--- /dev/null
+++ b/charts/hedgedoc/tests/__snapshot__/98_snapshot_test.yaml.snap
@@ -0,0 +1,144 @@
+should match basic snapshot:
+  1: |
+    apiVersion: v1
+    data:
+      CMD_DB_DATABASE: hedgedoc
+      CMD_DB_HOST: RELEASE-NAME-postgresql
+      CMD_DB_PORT: "5432"
+      CMD_DB_USERNAME: hedgedoc
+      CMD_DEFAULT_PERMISSION: freely
+      CMD_DOMAIN: hedgedoc.example.com
+      CMD_IMAGE_UPLOAD_TYPE: minio
+      CMD_MINIO_PORT: "443"
+      CMD_MINIO_SECURE: "true"
+      CMD_OAUTH2_SCOPE: openid email profile
+      CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR: name
+      CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR: email
+      CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR: preferred_username
+      CMD_PROTOCOL_USESSL: "true"
+      CMD_S3_BUCKET: hedgedoc
+      CMD_SESSION_LIFE: "3.6e+07"
+    kind: ConfigMap
+    metadata:
+      labels:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: hedgedoc
+        app.kubernetes.io/version: 4.5.6
+        helm.sh/chart: hedgedoc-1.2.3
+      name: RELEASE-NAME-hedgedoc
+  2: |
+    apiVersion: apps/v1
+    kind: Deployment
+    metadata:
+      labels:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: hedgedoc
+        app.kubernetes.io/version: 4.5.6
+        helm.sh/chart: hedgedoc-1.2.3
+      name: RELEASE-NAME-hedgedoc
+    spec:
+      replicas: 1
+      selector:
+        matchLabels:
+          app.kubernetes.io/instance: RELEASE-NAME
+          app.kubernetes.io/name: hedgedoc
+      strategy:
+        type: Recreate
+      template:
+        metadata:
+          labels:
+            app.kubernetes.io/instance: RELEASE-NAME
+            app.kubernetes.io/name: hedgedoc
+        spec:
+          containers:
+            - env:
+                - name: CMD_DB_PASSWORD
+                  valueFrom:
+                    secretKeyRef:
+                      key: password
+                      name: RELEASE-NAME-postgresql
+              envFrom:
+                - configMapRef:
+                    name: RELEASE-NAME-hedgedoc
+              image: quay.io/hedgedoc/hedgedoc:4.5.6
+              imagePullPolicy: IfNotPresent
+              livenessProbe:
+                httpGet:
+                  path: /_health
+                  port: http
+              name: hedgedoc
+              ports:
+                - containerPort: 3000
+                  name: http
+                  protocol: TCP
+              readinessProbe:
+                httpGet:
+                  path: /_health
+                  port: http
+              resources: {}
+              securityContext: {}
+          securityContext: {}
+          serviceAccountName: RELEASE-NAME-hedgedoc
+  3: |
+    apiVersion: networking.k8s.io/v1
+    kind: Ingress
+    metadata:
+      labels:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: hedgedoc
+        app.kubernetes.io/version: 4.5.6
+        helm.sh/chart: hedgedoc-1.2.3
+      name: RELEASE-NAME-hedgedoc
+    spec:
+      rules:
+        - host: hedgedoc.example.com
+          http:
+            paths:
+              - backend:
+                  service:
+                    name: RELEASE-NAME-hedgedoc
+                    port:
+                      number: 80
+                path: /
+                pathType: ImplementationSpecific
+  4: |
+    apiVersion: v1
+    data: null
+    kind: Secret
+    metadata:
+      name: dotfile-secret
+  5: |
+    apiVersion: v1
+    kind: Service
+    metadata:
+      labels:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: hedgedoc
+        app.kubernetes.io/version: 4.5.6
+        helm.sh/chart: hedgedoc-1.2.3
+      name: RELEASE-NAME-hedgedoc
+    spec:
+      ports:
+        - name: http
+          port: 80
+          protocol: TCP
+          targetPort: http
+      selector:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/name: hedgedoc
+      type: ClusterIP
+  6: |
+    apiVersion: v1
+    kind: ServiceAccount
+    metadata:
+      labels:
+        app.kubernetes.io/instance: RELEASE-NAME
+        app.kubernetes.io/managed-by: Helm
+        app.kubernetes.io/name: hedgedoc
+        app.kubernetes.io/version: 4.5.6
+        helm.sh/chart: hedgedoc-1.2.3
+      name: RELEASE-NAME-hedgedoc
diff --git a/charts/hedgedoc/tests/mocks/test.yaml b/charts/hedgedoc/tests/mocks/test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..95e57c375e87c98bb1aca829c5616d7f51a662a2
--- /dev/null
+++ b/charts/hedgedoc/tests/mocks/test.yaml
@@ -0,0 +1,2 @@
+ingress:
+  enabled: true
\ No newline at end of file
diff --git a/charts/hedgedoc/values.yaml b/charts/hedgedoc/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..32a9bb98c36a39d38d7eaa47a08a739e92ca391d
--- /dev/null
+++ b/charts/hedgedoc/values.yaml
@@ -0,0 +1,110 @@
+# Default values for hedgedoc.
+image:
+  repository: quay.io/hedgedoc/hedgedoc
+  # -- configures image pull policy for hedgedoc deployment
+  pullPolicy: IfNotPresent
+  # -- Overrides the image tag whose default is the chart appVersion.
+  tag: ""
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+  # Specifies whether a service account should be created
+  create: true
+  # Annotations to add to the service account
+  annotations: {}
+  # The name of the service account to use.
+  # If not set and create is true, a name is generated using the fullname template
+  name: ""
+
+config:
+  domain: null
+  allowFreeUrl: false
+  email: false
+  protocolUseSsl: true
+  urlAddPort: false
+  useCdn: false
+  defaultPermission: freely
+  session:
+    lifeTime: 36000000
+    secret: null
+  github:
+    clientId: null
+    clientSecret: null
+  minio:
+    accessKey: null
+    secretKey: null
+    endpoint: null
+    port: 443
+    secure: true
+  s3bucket: hedgedoc
+  oauth:
+    providerName: null
+    clientId: null
+    clientSecret: null
+    authorisationUrl: null
+    tokenUrl: null
+    userProfileUrl: null
+    userProfileUsername: preferred_username
+    userProfileDisplayName: name
+    userProfileEmailAttr: email
+    scope: openid email profile
+
+
+postgresql:
+  enabled: true
+  auth:
+    database: hedgedoc
+    username: hedgedoc
+    password: ""
+    existingSecret: ""
+
+
+podAnnotations: {}
+
+podSecurityContext: {}
+  # fsGroup: 2000
+
+securityContext: {}
+  # capabilities:
+  #   drop:
+  #   - ALL
+  # readOnlyRootFilesystem: true
+  # runAsNonRoot: true
+  # runAsUser: 1000
+
+service:
+  type: ClusterIP
+  port: 80
+
+ingress:
+  enabled: false
+  className: ""
+  annotations: {}
+    # kubernetes.io/ingress.class: nginx
+    # kubernetes.io/tls-acme: "true"
+  hosts:
+    - host: hedgedoc.example.com
+      paths:
+        - path: /
+          pathType: ImplementationSpecific
+  tls: []
+  #  - secretName: chart-example-tls
+  #    hosts:
+  #      - chart-example.local
+
+resources: {}
+  # limits:
+  #   cpu: 100m
+  #   memory: 512Mi
+  # requests:
+  #   cpu: 100m
+  #   memory: 512Mi
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}