diff --git a/deployment/helmchart/.helmignore b/deployment/helmchart/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778
--- /dev/null
+++ b/deployment/helmchart/.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/deployment/helmchart/Chart.yaml b/deployment/helmchart/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..74c365d79e93be2be17a8e24fe484cb34efa4977
--- /dev/null
+++ b/deployment/helmchart/Chart.yaml
@@ -0,0 +1,24 @@
+annotations:
+  category: Dashboard
+apiVersion: v2
+appVersion: 0.1.0
+dependencies:
+  - name: common
+    repository: https://charts.bitnami.com/bitnami
+    tags:
+      - bitnami-common
+    version: 1.x.x
+description: A Helm chart for deploying the Stackspin Dashboard to Kubernetes
+engine: gotpl
+home: https://open.greenhost.net/openappstack/admin-frontend/
+icon: https://open.greenhost.net/openappstack/admin-frontend/-/blob/master/public/assets/logo.svg
+keywords:
+  - stackspin
+  - dashboard
+maintainers:
+  - email: info@openappstack.net
+    name: Stackspin
+name: admin-frontend
+sources:
+  - https://open.greenhost.net/openappstack/admin-frontend/
+version: 0.1.0
diff --git a/deployment/helmchart/templates/NOTES.txt b/deployment/helmchart/templates/NOTES.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8caea6184a7ed58421fd566b029085d4c64bd3a6
--- /dev/null
+++ b/deployment/helmchart/templates/NOTES.txt
@@ -0,0 +1,165 @@
+{{- $secretName := include "discourse.secretName" . -}}
+{{- $postgresqlSecretName := include "discourse.postgresql.secretName" . -}}
+{{- $redisSecretName := include "discourse.redis.secretName" . -}}
+
+{{- if or .Values.postgresql.enabled .Values.externalDatabase.host -}}
+
+{{- if empty (include "discourse.host" .) -}}
+###############################################################################
+### ERROR: You did not provide an external host in your 'helm install' call ###
+###############################################################################
+
+This deployment will be incomplete until you configure Discourse with a resolvable host. To configure Discourse with the URL of your service:
+
+1. Get the discourse URL by running:
+
+  {{- if contains "NodePort" .Values.service.type }}
+  export DISCOURSE_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}"):$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} -o jsonpath="{.spec.ports[0].nodePort}")
+  {{- else if contains "LoadBalancer" .Values.service.type }}
+  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+        Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}'
+
+  export DISCOURSE_HOST=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
+  {{- end }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $secretName "field" "discourse-password" "context" $) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $postgresqlSecretName "field" "postgresql-password" "context" $) }}
+  {{- if (include "discourse.redis.auth.enabled" .) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $redisSecretName "field" "redis-password" "context" $) }}
+  {{- end }}
+
+2. Complete your Discourse deployment by running:
+
+{{- if .Values.postgresql.enabled }}
+
+  helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} bitnami/{{ .Chart.Name }} \
+    --set discourse.host=$DISCOURSE_HOST \
+    --set discourse.password=$DISCOURSE_PASSWORD \
+    {{- if .Values.global }}{{- if .Values.global.imagePullSecrets }}
+    --set global.imagePullSecrets={{ .Values.global.imagePullSecrets }} \
+    {{- end }}{{- end }}
+    {{- if and .Values.redis.enabled .Values.redis.auth.enabled (not .Values.redis.auth.existingSecret) (not .Values.redis.auth.password) }}
+    --set redis.auth.password=$REDIS_PASSWORD \
+    {{- end }}
+    --set postgresql.postgresqlPassword=$POSTGRESQL_PASSWORD
+
+{{- else }}
+
+  ## PLEASE UPDATE THE EXTERNAL DATABASE CONNECTION PARAMETERS IN THE FOLLOWING COMMAND AS NEEDED ##
+
+  helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} bitnami/{{ .Chart.Name }} \
+    --set discourse.host=$DISCOURSE_HOST \
+    --set discourse.password=$DISCOURSE_PASSWORD \
+    --set service.type={{ .Values.service.type }} \
+    --set externalDatabase.host={{ .Values.externalDatabase.host }} \
+    --set externalDatabase.port={{ .Values.externalDatabase.port }} \
+    --set externalDatabase.user={{ .Values.externalDatabase.user }} \
+    --set externalDatabase.password=$POSTGRESQL_PASSWORD \
+    --set externalDatabase.database={{ .Values.externalDatabase.database }} \
+    {{- if .Values.global }}{{- if .Values.global.imagePullSecrets }}
+    --set global.imagePullSecrets={{ .Values.global.imagePullSecrets }} \
+    {{- end }}{{- end }}
+    {{- if and .Values.redis.enabled .Values.redis.auth.enabled (not .Values.redis.auth.existingSecret) (not .Values.redis.auth.password) }}
+    --set redis.auth.password=$REDIS_PASSWORD \
+    {{- end }}
+    --set postgresql.enabled=false
+{{- end }}
+
+{{- else -}}
+
+1. Get the Discourse URL by running:
+
+  Discourse URL : http://{{ include "discourse.host" . }}/
+
+{{- if eq .Values.service.type "ClusterIP" }}
+  kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "common.names.fullname" . }} 80:{{ .Values.service.port }}
+{{- end }}
+
+2. Get your Discourse login credentials by running:
+
+  Username: {{ .Values.discourse.username }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $secretName "field" "discourse-password" "context" $) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $postgresqlSecretName "field" "postgresql-password" "context" $) }}
+  {{- if (include "discourse.redis.auth.enabled" .) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $redisSecretName "field" "redis-password" "context" $) }}
+  {{- end }}
+
+{{- end }}
+
+{{- else -}}
+
+########################################################################################
+### ERROR: You did not provide an external database host in your 'helm install' call ###
+########################################################################################
+
+This deployment will be incomplete until you configure Discourse with a resolvable database host. To configure Discourse to use and external database host:
+
+1. Complete your Discourse deployment by running:
+
+{{- if contains "NodePort" .Values.service.type }}
+  export DISCOURSE_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}"):$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} -o jsonpath="{.spec.ports[0].nodePort}")
+{{- else if contains "LoadBalancer" .Values.service.type }}
+
+  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+        Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}'
+
+  export DISCOURSE_HOST=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
+{{- else }}
+
+  export DISCOURSE_HOST=127.0.0.1
+{{- end }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $secretName "field" "discourse-password" "context" $) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $postgresqlSecretName "field" "postgresql-password" "context" $) }}
+  {{- if (include "discourse.redis.auth.enabled" .) }}
+  {{ include "common.utils.secret.getvalue" (dict "secret" $redisSecretName "field" "redis-password" "context" $) }}
+  {{- end }}
+
+
+  ## PLEASE UPDATE THE EXTERNAL DATABASE CONNECTION PARAMETERS IN THE FOLLOWING COMMAND AS NEEDED ##
+
+  helm upgrade --namespace {{ .Release.Namespace }} {{ .Release.Name }} bitnami/{{ .Chart.Name }} \
+    --set discourse.host=$DISCOURSE_HOST \
+    --set discourse.password=$DISCOURSE_PASSWORD \
+    --set postgresql.enabled=false \
+    {{- if not (empty .Values.externalDatabase.user) }}
+    --set externalDatabase.user={{ .Values.externalDatabase.user }} \
+    {{- end }}
+    {{- if not (empty .Values.externalDatabase.password) }}
+    --set externalDatabase.password=$POSTGRESQL_PASSWORD \
+    {{- end }}
+    {{- if not (empty .Values.externalDatabase.database) }}
+    --set externalDatabase.database={{ .Values.externalDatabase.database }}
+    {{- end }}
+    --set externalDatabase.host=YOUR_EXTERNAL_DATABASE_HOST \
+    {{- if .Values.global }}{{- if .Values.global.imagePullSecrets }}
+    --set global.imagePullSecrets={{ .Values.global.imagePullSecrets }} \
+    {{- end }}{{- end }}
+    {{- if and .Values.redis.enabled .Values.redis.auth.enabled (not .Values.redis.auth.existingSecret) (not .Values.redis.auth.password) }}
+    --set redis.auth.password=$REDIS_PASSWORD \
+    {{- end }}
+    --set service.type={{ .Values.service.type }}
+{{- end }}
+
+{{ if and .Values.postgresql.enabled (not .Values.postgresql.existingSecret) (eq .Values.postgresql.postgresqlPostgresPassword "bitnami") -}}
+#####################################################################################
+### WARNING: You did not change the default password for the PostgreSQL root user ###
+#####################################################################################
+{{- end }}
+
+{{- include "common.warnings.rollingTag" .Values.image }}
+
+{{- $passwordValidationErrors := list -}}
+{{- if not .Values.discourse.existingSecret -}}
+    {{- $requiredDiscoursePassword := dict "valueKey" "discourse.password" "secret" $secretName "field" "discourse-password" "context" $ -}}
+    {{- $requiredDiscoursePasswordError := include "common.validations.values.single.empty" $requiredDiscoursePassword -}}
+    {{- $passwordValidationErrors = append $passwordValidationErrors $requiredDiscoursePasswordError -}}
+{{- end -}}
+
+{{- $postgresqlPasswordValidationErrors := include "common.validations.values.postgresql.passwords" (dict "secret" $postgresqlSecretName "subchart" true "context" $) -}}
+{{- $passwordValidationErrors = append $passwordValidationErrors $postgresqlPasswordValidationErrors -}}
+
+{{- if (include "discourse.redis.auth.enabled" .) }}
+{{- $redisPasswordValidationErrors := include "common.validations.values.redis.passwords" (dict "secret" $redisSecretName "subchart" true "context" $) -}}
+{{- $passwordValidationErrors = append $passwordValidationErrors $redisPasswordValidationErrors -}}
+{{- end }}
+
+{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $) -}}
diff --git a/deployment/helmchart/templates/_helpers.tpl b/deployment/helmchart/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..9bc649d984105000ca2973b3be5dd1b4eb014a7d
--- /dev/null
+++ b/deployment/helmchart/templates/_helpers.tpl
@@ -0,0 +1,249 @@
+
+{{/*
+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).
+*/}}
+{{- define "postgresql.fullname" -}}
+{{- printf "%s-%s" .Release.Name "postgresql" | 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).
+*/}}
+{{- define "redis.fullname" -}}
+{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "discourse.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create -}}
+    {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }}
+{{- else -}}
+    {{ default "default" .Values.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the proper Docker image registry secret names
+*/}}
+{{- define "discourse.imagePullSecrets" -}}
+{{ include "common.images.pullSecrets" (dict "images" (list .Values.image) "global" .Values.global) }}
+{{- end -}}
+
+{{/*
+Return true if a secret object for Discourse should be created
+*/}}
+{{- define "discourse.createSecret" -}}
+{{- if or (not .Values.discourse.existingSecret) (and (not .Values.discourse.smtp.existingSecret) .Values.discourse.smtp.password .Values.discourse.smtp.enabled) }}
+    {{- true -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Discourse secret name
+*/}}
+{{- define "discourse.secretName" -}}
+{{- if .Values.discourse.existingSecret }}
+    {{- printf "%s" .Values.discourse.existingSecret -}}
+{{- else -}}
+    {{- printf "%s-discourse" (include "common.names.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Discourse SMTP secret name
+*/}}
+{{- define "discourse.smtp.secretName" -}}
+{{- if .Values.discourse.smtp.existingSecret }}
+    {{- printf "%s" .Values.discourse.smtp.existingSecret -}}
+{{- else -}}
+    {{- printf "%s-discourse" (include "common.names.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return true if Discourse SMTP uses password authentication
+*/}}
+{{- define "discourse.smtp.password.enabled" -}}
+{{- if and (or .Values.discourse.smtp.password .Values.discourse.smtp.existingSecret) .Values.discourse.smtp.enabled }}
+    {{- true -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Get the user defined LoadBalancerIP for this release
+Note, returns 127.0.0.1 if using ClusterIP.
+*/}}
+{{- define "discourse.serviceIP" -}}
+{{- if eq .Values.service.type "ClusterIP" -}}
+127.0.0.1
+{{- else -}}
+{{- .Values.service.loadBalancerIP | default "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Gets the host to be used for this application.
+If not using ClusterIP, or if a host or LoadBalancerIP is not defined, the value will be empty
+*/}}
+{{- define "discourse.host" -}}
+{{- $host := .Values.discourse.host | default "" -}}
+{{- default (include "discourse.serviceIP" .) $host -}}
+{{- end -}}
+
+{{/*
+Return the proper Discourse image name
+*/}}
+{{- define "discourse.image" -}}
+{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }}
+{{- end -}}
+
+{{/*
+Return the proper Storage Class
+*/}}
+{{- define "discourse.storageClass" -}}
+{{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) -}}
+{{- end -}}
+
+{{/*
+Return the Postgresql hostname
+*/}}
+{{- define "discourse.databaseHost" -}}
+{{- if .Values.postgresql.enabled }}
+    {{- printf "%s" (include "postgresql.fullname" .) -}}
+{{- else -}}
+    {{- printf "%s" .Values.externalDatabase.host -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Postgresql port
+*/}}
+{{- define "discourse.databasePort" -}}
+{{- if .Values.postgresql.enabled }}
+    {{- printf "5432" | quote -}}
+{{- else -}}
+    {{- .Values.externalDatabase.port | quote -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Postgresql database name
+*/}}
+{{- define "discourse.databaseName" -}}
+{{- if .Values.postgresql.enabled }}
+    {{- printf "%s" .Values.postgresql.postgresqlDatabase -}}
+{{- else -}}
+    {{- printf "%s" .Values.externalDatabase.database -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Postgresql user
+*/}}
+{{- define "discourse.databaseUser" -}}
+{{- if .Values.postgresql.enabled }}
+    {{- printf "%s" .Values.postgresql.postgresqlUsername -}}
+{{- else -}}
+    {{- printf "%s" .Values.externalDatabase.user -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return true if a secret object for Postgres should be created
+*/}}
+{{- define "discourse.postgresql.createSecret" -}}
+{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.existingSecret) }}
+    {{- true -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Postgresql secret name
+*/}}
+{{- define "discourse.postgresql.secretName" -}}
+{{- if .Values.postgresql.enabled }}
+    {{- if .Values.postgresql.existingSecret }}
+        {{- printf "%s" .Values.postgresql.existingSecret -}}
+    {{- else -}}
+        {{- printf "%s" (include "postgresql.fullname" .) -}}
+    {{- end -}}
+{{- else if .Values.externalDatabase.existingSecret }}
+    {{- printf "%s" .Values.externalDatabase.existingSecret -}}
+{{- else -}}
+    {{- printf "%s-database" (include "common.names.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Redis™ hostname
+*/}}
+{{- define "discourse.redisHost" -}}
+{{- if .Values.redis.enabled }}
+    {{- printf "%s-master" (include "redis.fullname" .) -}}
+{{- else -}}
+    {{- printf "%s" .Values.externalRedis.host -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Redis™ port
+*/}}
+{{- define "discourse.redisPort" -}}
+{{- if .Values.redis.enabled }}
+    {{- printf "6379" | quote -}}
+{{- else -}}
+    {{- .Values.externalRedis.port | quote -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return true if a secret object for Redis™ should be created
+*/}}
+{{- define "discourse.redis.createSecret" -}}
+{{- if and (not .Values.redis.enabled) (not .Values.externalRedis.existingSecret) .Values.externalRedis.password }}
+    {{- true -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Redis™ secret name
+*/}}
+{{- define "discourse.redis.secretName" -}}
+{{- if .Values.redis.enabled }}
+    {{- if .Values.redis.auth.existingSecret }}
+        {{- printf "%s" .Values.redis.auth.existingSecret -}}
+    {{- else -}}
+        {{- printf "%s" (include "redis.fullname" .) -}}
+    {{- end -}}
+{{- else if .Values.externalRedis.existingSecret }}
+    {{- printf "%s" .Values.externalRedis.existingSecret -}}
+{{- else -}}
+    {{- printf "%s-redis" (include "common.names.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the Redis™ secret key
+*/}}
+{{- define "discourse.redis.secretPasswordKey" -}}
+{{- if and .Values.redis.enabled .Values.redis.auth.existingSecret }}
+    {{- required "You need to provide existingSecretPasswordKey when an existingSecret is specified in redis" .Values.redis.auth.existingSecretPasswordKey | printf "%s" }}
+{{- else if and (not .Values.redis.enabled) .Values.externalRedis.existingSecret }}
+    {{- required "You need to provide existingSecretPasswordKey when an existingSecret is specified in redis" .Values.externalRedis.existingSecretPasswordKey | printf "%s" }}
+{{- else -}}
+    {{- printf "redis-password" -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return whether Redis™ uses password authentication or not
+*/}}
+{{- define "discourse.redis.auth.enabled" -}}
+{{- if or (and .Values.redis.enabled .Values.redis.auth.enabled) (and (not .Values.redis.enabled) (or .Values.externalRedis.password .Values.externalRedis.existingSecret)) }}
+    {{- true -}}
+{{- end -}}
+{{- end -}}
diff --git a/deployment/helmchart/templates/configmaps.yaml b/deployment/helmchart/templates/configmaps.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cded68db5c3b0451ec52fe43fad11de5a182064c
--- /dev/null
+++ b/deployment/helmchart/templates/configmaps.yaml
@@ -0,0 +1,50 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ template "common.names.fullname" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+data:
+  {{- $port := .Values.service.port | toString }}
+  DISCOURSE_HOST: "{{ include "discourse.host" . }}"
+  DISCOURSE_SKIP_INSTALL: {{ ternary "yes" "no" .Values.discourse.skipInstall | quote }}
+  DISCOURSE_SITE_NAME: {{ .Values.discourse.siteName | quote }}
+  DISCOURSE_USERNAME: {{ .Values.discourse.username | quote }}
+  DISCOURSE_EMAIL: {{ .Values.discourse.email | quote }}
+  DISCOURSE_REDIS_HOST: {{ template "discourse.redisHost" . }}
+  DISCOURSE_REDIS_PORT_NUMBER: {{ template "discourse.redisPort" . }}
+  DISCOURSE_DATABASE_HOST: {{ template "discourse.databaseHost" . }}
+  DISCOURSE_DATABASE_PORT_NUMBER: {{ template "discourse.databasePort" . }}
+  DISCOURSE_DATABASE_NAME: {{ template "discourse.databaseName" . }}
+  DISCOURSE_DATABASE_USER: {{ template "discourse.databaseUser" . }}
+  {{- if .Values.discourse.smtp.enabled }}
+  DISCOURSE_SMTP_HOST: {{ .Values.discourse.smtp.host | quote }}
+  DISCOURSE_SMTP_PORT: {{ .Values.discourse.smtp.port | quote }}
+  {{- if .Values.discourse.smtp.user }}
+  DISCOURSE_SMTP_USER: {{ .Values.discourse.smtp.user | quote }}
+  {{- end }}
+  {{- if .Values.discourse.smtp.protocol }}
+  DISCOURSE_SMTP_PROTOCOL: {{ .Values.discourse.smtp.protocol | quote }}
+  {{- end }}
+  {{- if .Values.discourse.smtp.auth }}
+  DISCOURSE_SMTP_AUTH: {{ .Values.discourse.smtp.auth | quote }}
+  {{- end }}
+  {{- end }}
+  {{- if or .Values.postgresql.enabled .Values.externalDatabase.create }}
+  POSTGRESQL_CLIENT_DATABASE_HOST: {{ template "discourse.databaseHost" . }}
+  POSTGRESQL_CLIENT_DATABASE_PORT_NUMBER: {{ template "discourse.databasePort" . }}
+  {{- if or .Values.postgresql.enabled (not .Values.externalDatabase.postgresqlPostgresUser) }}
+  POSTGRESQL_CLIENT_POSTGRES_USER: "postgres"
+  {{- else }}
+  POSTGRESQL_CLIENT_POSTGRES_USER: {{ .Values.externalDatabase.postgresqlPostgresUser | quote }}
+  POSTGRESQL_CLIENT_CREATE_DATABASE_USERNAME: {{ .Values.externalDatabase.user | quote }}
+  POSTGRESQL_CLIENT_CREATE_DATABASE_PASSWORD: {{ .Values.externalDatabase.password | quote }}
+  {{- end }}
+  POSTGRESQL_CLIENT_CREATE_DATABASE_NAME: {{ template "discourse.databaseName" . }}
+  POSTGRESQL_CLIENT_CREATE_DATABASE_EXTENSIONS: "hstore,pg_trgm"
+  {{- end }}
diff --git a/deployment/helmchart/templates/deployment.yaml b/deployment/helmchart/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7a94f21e2a43243360e20141dbe5cc74732bb7c1
--- /dev/null
+++ b/deployment/helmchart/templates/deployment.yaml
@@ -0,0 +1,275 @@
+{{- if and (include "discourse.host" .) (or .Values.postgresql.enabled .Values.externalDatabase.host) -}}
+apiVersion: {{ template "common.capabilities.deployment.apiVersion" . }}
+kind: Deployment
+metadata:
+  name: {{ template "common.names.fullname" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+    component: discourse
+    {{- if .Values.commonLabels }}
+    {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+    {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }}
+      component: discourse
+  {{- if .Values.updateStrategy }}
+  strategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
+  {{- end }}
+  template:
+    metadata:
+      annotations:
+        checksum/config: {{ include (print $.Template.BasePath "/configmaps.yaml") . | sha256sum }}
+        checksum/secrets-discourse: {{ include (print $.Template.BasePath "/secrets-discourse.yaml") . | sha256sum }}
+        checksum/secrets-database: {{ include (print $.Template.BasePath "/secrets-database.yaml") . | sha256sum }}
+        checksum/secrets-redis: {{ include (print $.Template.BasePath "/secrets-redis.yaml") . | sha256sum }}
+      labels: {{- include "common.labels.standard" . | nindent 8 }}
+        component: discourse
+        {{- if .Values.podLabels }}
+        {{- include "common.tplvalues.render" (dict "value" .Values.podLabels "context" $) | nindent 8 }}
+        {{- end }}
+      {{- if .Values.podAnnotations }}
+      annotations: {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
+      {{- end }}
+    spec:
+      {{- include "discourse.imagePullSecrets" . | nindent 6 }}
+      {{- if .Values.hostAliases }}
+      hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }}
+      {{- end }}
+      {{- if .Values.affinity }}
+      affinity: {{- include "common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }}
+      {{- else }}
+      affinity:
+        podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset "context" $) | nindent 10 }}
+        podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "context" $) | nindent 10 }}
+        nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }}
+      {{- end }}
+      {{- if .Values.nodeSelector }}
+      nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }}
+      {{- end }}
+      {{- if .Values.tolerations }}
+      tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.tolerations "context" $) | nindent 8 }}
+      {{- end }}
+      serviceAccountName: {{ include "discourse.serviceAccountName" . }}
+      securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      initContainers:
+        {{- if .Values.initContainers }}
+        {{- include "common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }}
+        {{- end }}
+        {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
+        - name: volume-permissions
+          image: {{ include "discourse.image" . }}
+          imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }}
+          command:
+            - sh
+            - -c
+            - |
+              mkdir -p "/bitnami/discourse"
+              chown -R "discourse:root" "/bitnami/discourse"
+          securityContext:
+            runAsUser: 0
+          {{- if .Values.volumePermissions.resources }}
+          resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }}
+          {{- end }}
+          volumeMounts:
+            - name: discourse-data
+              mountPath: /bitnami/discourse
+        {{- end }}
+      containers:
+        - name: discourse
+          securityContext: {{- toYaml .Values.discourse.containerSecurityContext | nindent 12 }}
+          image: {{ template "discourse.image" . }}
+          imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
+          {{- if .Values.discourse.command }}
+          command: {{- include "common.tplvalues.render" (dict "value" .Values.discourse.command "context" $) | nindent 12 }}
+          {{- end }}
+          {{- if .Values.discourse.args }}
+          args: {{- include "common.tplvalues.render" (dict "value" .Values.discourse.args "context" $) | nindent 12 }}
+          {{- end }}
+          env:
+            - name: BITNAMI_DEBUG
+              value: {{ ternary "true" "false" .Values.image.debug | quote }}
+            - name: DISCOURSE_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.secretName" . }}
+                  key: discourse-password
+            - name: DISCOURSE_DATABASE_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.postgresql.secretName" . }}
+                  key: postgresql-password
+            {{- if or .Values.postgresql.enabled .Values.externalDatabase.create }}
+            - name: POSTGRESQL_CLIENT_POSTGRES_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.postgresql.secretName" . }}
+                  key: postgresql-postgres-password
+            {{- end }}
+            {{- if (include "discourse.redis.auth.enabled" .) }}
+            - name: DISCOURSE_REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.redis.secretName" . }}
+                  key: {{ include "discourse.redis.secretPasswordKey" . }}
+            {{- end }}
+            {{- if (include "discourse.smtp.password.enabled" .) }}
+            - name: DISCOURSE_SMTP_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.smtp.secretName" . }}
+                  key: smtp-password
+            {{- end }}
+            {{- if .Values.discourse.extraEnvVars }}
+            {{- include "common.tplvalues.render" (dict "value" .Values.discourse.extraEnvVars "context" $) | nindent 12 }}
+            {{- end }}
+          envFrom:
+            - configMapRef:
+                name: {{ include "common.names.fullname" . }}
+            {{- if .Values.discourse.extraEnvVarsCM }}
+            - configMapRef:
+                name: {{ .Values.discourse.extraEnvVarsCM }}
+            {{- end }}
+            {{- if .Values.discourse.extraEnvVarsSecret }}
+            - secretRef:
+                name: {{ .Values.discourse.extraEnvVarsSecret }}
+            {{- end }}
+          ports:
+            - name: http
+              containerPort: 3000
+              protocol: TCP
+          {{- if .Values.discourse.livenessProbe.enabled }}
+          livenessProbe:
+            httpGet:
+              path: /srv/status
+              port: http
+            initialDelaySeconds: {{ .Values.discourse.livenessProbe.initialDelaySeconds }}
+            periodSeconds: {{ .Values.discourse.livenessProbe.periodSeconds }}
+            timeoutSeconds: {{ .Values.discourse.livenessProbe.timeoutSeconds }}
+            successThreshold: {{ .Values.discourse.livenessProbe.successThreshold }}
+            failureThreshold: {{ .Values.discourse.livenessProbe.failureThreshold }}
+          {{- else if .Values.discourse.customLivenessProbe }}
+          livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.discourse.customLivenessProbe "context" $) | nindent 12 }}
+          {{- end }}
+          {{- if .Values.discourse.readinessProbe.enabled }}
+          readinessProbe:
+            httpGet:
+              path: /srv/status
+              port: http
+            initialDelaySeconds: {{ .Values.discourse.readinessProbe.initialDelaySeconds }}
+            periodSeconds: {{ .Values.discourse.readinessProbe.periodSeconds }}
+            timeoutSeconds: {{ .Values.discourse.readinessProbe.timeoutSeconds }}
+            successThreshold: {{ .Values.discourse.readinessProbe.successThreshold }}
+            failureThreshold: {{ .Values.discourse.readinessProbe.failureThreshold }}
+          {{- else if .Values.discourse.customReadinessProbe }}
+          readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.discourse.customReadinessProbe "context" $) | nindent 12 }}
+          {{- end }}
+          volumeMounts:
+            - name: discourse-data
+              mountPath: /bitnami/discourse
+              subPath: discourse
+            {{- if .Values.discourse.extraVolumeMounts }}
+            {{- include "common.tplvalues.render" (dict "value" .Values.discourse.extraVolumeMounts "context" $) | nindent 12 }}
+            {{- end }}
+          {{- if .Values.discourse.resources }}
+          resources: {{- toYaml .Values.discourse.resources | nindent 12 }}
+          {{- end }}
+        - name: sidekiq
+          securityContext: {{- toYaml .Values.sidekiq.containerSecurityContext | nindent 12 }}
+          image: {{ template "discourse.image" . }}
+          imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
+          command: {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.command "context" $) | nindent 12 }}
+          args: {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.args "context" $) | nindent 12 }}
+          env:
+            - name: BITNAMI_DEBUG
+              value: {{ ternary "true" "false" .Values.image.debug | quote }}
+            - name: DISCOURSE_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.secretName" . }}
+                  key: discourse-password
+            - name: DISCOURSE_POSTGRESQL_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.postgresql.secretName" . }}
+                  key: postgresql-password
+            {{- if (include "discourse.redis.auth.enabled" .) }}
+            - name: REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.redis.secretName" . }}
+                  key: {{ include "discourse.redis.secretPasswordKey" . }}
+            {{- end }}
+            {{- if (include "discourse.smtp.password.enabled" .) }}
+            - name: DISCOURSE_SMTP_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "discourse.smtp.secretName" . }}
+                  key: smtp-password
+            {{- end }}
+            {{- if .Values.sidekiq.extraEnvVars }}
+            {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.extraEnvVars "context" $) | nindent 12 }}
+            {{- end }}
+          envFrom:
+            - configMapRef:
+                name: {{ include "common.names.fullname" . }}
+            {{- if .Values.sidekiq.extraEnvVarsCM }}
+            - configMapRef:
+                name: {{ .Values.sidekiq.extraEnvVarsCM }}
+            {{- end }}
+            {{- if .Values.sidekiq.extraEnvVarsSecret }}
+            - secretRef:
+                name: {{ .Values.sidekiq.extraEnvVarsSecret }}
+            {{- end }}
+          {{- if .Values.sidekiq.livenessProbe.enabled }}
+          livenessProbe:
+            exec:
+              command: ["/bin/sh", "-c", "pgrep -f ^sidekiq"]
+            initialDelaySeconds: {{ .Values.sidekiq.livenessProbe.initialDelaySeconds }}
+            periodSeconds: {{ .Values.sidekiq.livenessProbe.periodSeconds }}
+            timeoutSeconds: {{ .Values.sidekiq.livenessProbe.timeoutSeconds }}
+            successThreshold: {{ .Values.sidekiq.livenessProbe.successThreshold }}
+            failureThreshold: {{ .Values.sidekiq.livenessProbe.failureThreshold }}
+          {{- else if .Values.sidekiq.customLivenessProbe }}
+          livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.customLivenessProbe "context" $) | nindent 12 }}
+          {{- end }}
+          {{- if .Values.sidekiq.readinessProbe.enabled }}
+          readinessProbe:
+            exec:
+              command: ["/bin/sh", "-c", "pgrep -f ^sidekiq"]
+            initialDelaySeconds: {{ .Values.sidekiq.readinessProbe.initialDelaySeconds }}
+            periodSeconds: {{ .Values.sidekiq.readinessProbe.periodSeconds }}
+            timeoutSeconds: {{ .Values.sidekiq.readinessProbe.timeoutSeconds }}
+            successThreshold: {{ .Values.sidekiq.readinessProbe.successThreshold }}
+            failureThreshold: {{ .Values.sidekiq.readinessProbe.failureThreshold }}
+          {{- else if .Values.sidekiq.customReadinessProbe }}
+          readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.customReadinessProbe "context" $) | nindent 12 }}
+          {{- end }}
+          volumeMounts:
+            - name: discourse-data
+              mountPath: /bitnami/discourse
+              subPath: discourse
+            {{- if .Values.sidekiq.extraVolumeMounts }}
+            {{- include "common.tplvalues.render" (dict "value" .Values.sidekiq.extraVolumeMounts "context" $) | nindent 12 }}
+            {{- end }}
+          {{- if .Values.sidekiq.resources }}
+          resources: {{- toYaml .Values.sidekiq.resources | nindent 12 }}
+          {{- end }}
+        {{- if .Values.sidecars }}
+        {{- include "common.tplvalues.render" (dict "value" .Values.sidecars "context" $) | nindent 8 }}
+        {{- end }}
+      volumes:
+        - name: discourse-data
+          {{- if .Values.persistence.enabled }}
+          persistentVolumeClaim:
+            claimName: {{ .Values.persistence.existingClaim | default (include "common.names.fullname" .) }}
+          {{- else }}
+          emptyDir: {}
+          {{ end }}
+        {{- if .Values.extraVolumes }}
+        {{- include "common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }}
+        {{- end }}
+{{- end }}
diff --git a/deployment/helmchart/templates/ingress.yaml b/deployment/helmchart/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f266f581ceb5127b7381f12d79e739eef6c408b5
--- /dev/null
+++ b/deployment/helmchart/templates/ingress.yaml
@@ -0,0 +1,55 @@
+{{- if .Values.ingress.enabled -}}
+apiVersion: {{ template "common.capabilities.ingress.apiVersion" . }}
+kind: Ingress
+metadata:
+  name: {{ template "common.names.fullname" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if or .Values.ingress.annotations .Values.ingress.certManager .Values.commonAnnotations }}
+  annotations:
+  {{- if .Values.commonAnnotations }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.ingress.annotations }}
+  {{- toYaml .Values.ingress.annotations | nindent 4 }}
+  {{- end }}
+  {{- if .Values.ingress.certManager }}
+    kubernetes.io/tls-acme: "true"
+  {{- end }}
+  {{- end }}
+spec:
+  {{- if or .Values.ingress.tls .Values.ingress.extraTls }}
+  tls:
+    {{- if .Values.ingress.tls }}
+    - hosts:
+        - {{ .Values.ingress.hostname }}
+      secretName: {{ printf "%s-tls" .Values.ingress.hostname }}
+    {{- end }}
+    {{- if .Values.ingress.extraTls }}
+    {{- toYaml .Values.ingress.extraTls | nindent 4 }}
+    {{- end }}
+  {{- end }}
+  rules:
+    {{- if .Values.ingress.hostname }}
+    - host: {{ .Values.ingress.hostname }}
+      http:
+        paths:
+          - path: {{ .Values.ingress.path }}
+            {{- if eq "true" (include "common.ingress.supportsPathType" .) }}
+            pathType: {{ .Values.ingress.pathType }}
+            {{- end }}
+            backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" .) "servicePort" "http" "context" $)  | nindent 14 }}
+    {{- end }}
+    {{- range .Values.ingress.extraHosts }}
+    - host: {{ .name }}
+      http:
+        paths:
+          - path: {{ default "/" .path }}
+            {{- if eq "true" (include "common.ingress.supportsPathType" $) }}
+            pathType: {{ default "ImplementationSpecific" .pathType }}
+            {{- end }}
+            backend: {{- include "common.ingress.backend" (dict "serviceName" (include "common.names.fullname" $) "servicePort" "http" "context" $) | nindent 14 }}
+    {{- end }}
+{{- end }}
diff --git a/deployment/helmchart/templates/pvc.yaml b/deployment/helmchart/templates/pvc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..42e02c23056d60ff33e0b34d9ea8677583bb5a11
--- /dev/null
+++ b/deployment/helmchart/templates/pvc.yaml
@@ -0,0 +1,23 @@
+{{- if and (include "discourse.host" .) .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+  name: {{ template "common.names.fullname" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+spec:
+  accessModes:
+    - {{ .Values.persistence.accessMode | quote }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.size | quote }}
+  {{ include "discourse.storageClass" . }}
+  {{- if .Values.persistence.selector }}
+  selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 4 }}
+  {{- end -}}
+{{- end }}
diff --git a/deployment/helmchart/templates/secrets-database.yaml b/deployment/helmchart/templates/secrets-database.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d9f42f762895d3bc128270e8f97a57473a8bd70a
--- /dev/null
+++ b/deployment/helmchart/templates/secrets-database.yaml
@@ -0,0 +1,17 @@
+{{- if (include "discourse.postgresql.createSecret" .) }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "common.names.fullname" . }}-database
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+type: Opaque
+data:
+  postgresql-password: {{ .Values.externalDatabase.password | b64enc | quote }}
+  postgresql-postgres-password: {{ .Values.externalDatabase.postgresqlPostgresPassword | b64enc | quote }}
+{{- end }}
diff --git a/deployment/helmchart/templates/secrets-discourse.yaml b/deployment/helmchart/templates/secrets-discourse.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5f818100a44f2460fe93d4e2f08f2854cb2e6e55
--- /dev/null
+++ b/deployment/helmchart/templates/secrets-discourse.yaml
@@ -0,0 +1,23 @@
+{{- if (include "discourse.createSecret" .) }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "common.names.fullname" . }}-discourse
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+type: Opaque
+data:
+  {{- if and (.Values.discourse.password) (not .Values.discourse.existingSecret) }}
+  discourse-password: {{ .Values.discourse.password | b64enc | quote }}
+  {{- else if not .Values.discourse.existingSecret }}
+  discourse-password: {{ randAlphaNum 10 | b64enc | quote }}
+  {{- end }}
+  {{- if and (.Values.discourse.smtp.password) (.Values.discourse.smtp.enabled) (not .Values.discourse.smtp.existingSecret) }}
+  smtp-password: {{ .Values.discourse.smtp.password | b64enc | quote }}
+  {{- end }}
+{{- end }}
diff --git a/deployment/helmchart/templates/secrets-redis.yaml b/deployment/helmchart/templates/secrets-redis.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b854605b1329041980dd6aa572c2ba3ece5a2ba6
--- /dev/null
+++ b/deployment/helmchart/templates/secrets-redis.yaml
@@ -0,0 +1,16 @@
+{{- if (include "discourse.redis.createSecret" .) }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "common.names.fullname" . }}-redis
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+type: Opaque
+data:
+  redis-password: {{ .Values.externalRedis.password | b64enc | quote }}
+{{- end }}
diff --git a/deployment/helmchart/templates/service.yaml b/deployment/helmchart/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b196f3274177d7981ed9447b0e92b63efc0e8ae8
--- /dev/null
+++ b/deployment/helmchart/templates/service.yaml
@@ -0,0 +1,42 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "common.names.fullname" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if or .Values.service.annotations .Values.commonAnnotations}}
+  annotations:
+  {{- if .Values.service.annotations }}
+  {{- include "common.tplvalues.render" (dict "value" .Values.service.annotations "context" $) | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }}
+  {{- end }}
+  {{- end }}
+spec:
+  type: {{ .Values.service.type }}
+  {{- if (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }}
+  externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }}
+  {{- end }}
+  {{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }}
+  loadBalancerIP: {{ .Values.service.loadBalancerIP }}
+  {{- end }}
+  {{- if (and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges) }}
+  loadBalancerSourceRanges:
+  {{ toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
+  {{- end }}
+  ports:
+    - name: http
+      port: {{ .Values.service.port }}
+      targetPort: http
+      {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http))) }}
+      nodePort: {{ .Values.service.nodePorts.http }}
+      {{- else if eq .Values.service.type "ClusterIP" }}
+      nodePort: null
+      {{- end }}
+    {{- if .Values.service.extraPorts }}
+    {{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }}
+    {{- end }}
+  selector: {{- include "common.labels.matchLabels" . | nindent 4 }}
diff --git a/deployment/helmchart/templates/serviceaccount.yaml b/deployment/helmchart/templates/serviceaccount.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..acbe84183807a56ee8949a44c5c4dca193394650
--- /dev/null
+++ b/deployment/helmchart/templates/serviceaccount.yaml
@@ -0,0 +1,19 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "discourse.serviceAccountName" . }}
+  labels: {{- include "common.labels.standard" . | nindent 4 }}
+  {{- if .Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }}
+  annotations:
+  {{- if .Values.serviceAccount.annotations }}
+  {{- toYaml .Values.serviceAccount.annotations | nindent 4 }}
+  {{- end }}
+  {{- if .Values.commonAnnotations }}
+  {{- include "common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }}
+  {{- end }}
+  {{- end }}
+{{- end -}}
diff --git a/deployment/helmchart/templates/tls-secrets.yaml b/deployment/helmchart/templates/tls-secrets.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..090ce7ce48fffd30cc2e994339f84a69dd30d99b
--- /dev/null
+++ b/deployment/helmchart/templates/tls-secrets.yaml
@@ -0,0 +1,19 @@
+{{- if .Values.ingress.enabled }}
+{{- range .Values.ingress.secrets }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ .name }}
+  labels: {{- include "common.labels.standard" $ | nindent 4 }}
+  {{- if $.Values.commonLabels }}
+  {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
+  {{- end }}
+  {{- if $.Values.commonAnnotations }}
+  annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+  {{- end }}
+type: kubernetes.io/tls
+data:
+  tls.crt: {{ .certificate | b64enc }}
+  tls.key: {{ .key | b64enc }}
+{{- end }}
+{{- end }}
diff --git a/deployment/helmchart/values.yaml b/deployment/helmchart/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d5d25bd591d41bbe335ec3caad1965869a7c8105
--- /dev/null
+++ b/deployment/helmchart/values.yaml
@@ -0,0 +1,702 @@
+## @section Global parameters
+## Global Docker image parameters
+## Please, note that this will override the image parameters, including dependencies, configured to use the global value
+## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass
+
+## @param global.imageRegistry Global Docker image registry
+## @param global.imagePullSecrets Global Docker registry secret names as an array
+## @param global.storageClass Global StorageClass for Persistent Volume(s)
+##
+global:
+  imageRegistry: ""
+  ## E.g.
+  ## imagePullSecrets:
+  ##   - myRegistryKeySecretName
+  ##
+  imagePullSecrets: []
+  storageClass: ""
+
+## @section Common parameters
+
+## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set)
+##
+kubeVersion: ""
+## @param nameOverride String to partially override discourse.fullname template (will maintain the release name)
+##
+nameOverride: ""
+## @param fullnameOverride String to fully override discourse.fullname template
+##
+fullnameOverride: ""
+## @param commonLabels Labels to be added to all deployed resources
+##
+commonLabels: {}
+## @param commonAnnotations Annotations to be added to all deployed resources
+##
+commonAnnotations: {}
+
+
+## @section Service parameters
+
+## Kubernetes service configuration. For minikube, set this to NodePort, elsewhere use LoadBalancer or ClusterIP
+##
+service:
+  ## @param service.type Kubernetes Service type
+  ##
+  type: LoadBalancer
+  ## @param service.port Service HTTP port
+  ##
+  port: 80
+  ## @param service.nodePort Node Ports to expose
+  ##
+  nodePort: ""
+  ## @param service.loadBalancerIP Use loadBalancerIP to request a specific static IP
+  ##
+  loadBalancerIP: ""
+  ## @param service.externalTrafficPolicy Enable client source IP preservation
+  ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
+  ##
+  externalTrafficPolicy: Cluster
+  ## @param service.annotations Service annotations
+  ##
+  annotations: {}
+  ## @param service.loadBalancerSourceRanges Limits which cidr blocks can connect to service's load balancer
+  ## Only valid if service.type: LoadBalancer
+  ##
+  loadBalancerSourceRanges: []
+  ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value)
+  ##
+  extraPorts: []
+  ## @param service.nodePorts.http Kubernetes http node port
+  ## Example:
+  ##  nodePorts:
+  ##   http: <to set explicitly, choose port between 30000-32767>
+  ##
+  nodePorts:
+    http: ""
+
+## @section Discourse parameters
+
+## Bitnami Discourse image version
+## ref: https://hub.docker.com/r/bitnami/discourse/tags/
+## @param image.registry Discourse image registry
+## @param image.repository Discourse image repository
+## @param image.tag Discourse image tag
+## @param image.pullPolicy Discourse image pull policy
+## @param image.pullSecrets Discourse image pull secrets
+## @param image.debug Specify if debug logs should be enabled
+##
+image:
+  registry: docker.io
+  repository: bitnami/discourse
+  tag: 2.7.8-debian-10-r22
+  ## Specify a imagePullPolicy
+  ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
+  ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
+  ##
+  pullPolicy: IfNotPresent
+  ## Optionally specify an array of imagePullSecrets.
+  ## Secrets must be manually created in the namespace.
+  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+  ## e.g:
+  ## pullSecrets:
+  ##   - myRegistryKeySecretName
+  ##
+  pullSecrets: []
+  ## Set to true if you would like to see extra information on logs
+  ##
+  debug: false
+## @param imagePullSecrets Specify docker-registry secret names as an array
+##
+imagePullSecrets: []
+## Discourse configuration parameters
+## ref: https://github.com/bitnami/bitnami-docker-discourse#configuration
+##
+discourse:
+  ## @param discourse.host Discourse host to create application URLs (include the port if =/= 80)
+  ##
+  host: ""
+  ## @param discourse.siteName Discourse site name
+  ##
+  siteName: 'My Site!'
+  ## @param discourse.username Admin user of the application
+  ##
+  username: user
+  ## @param discourse.password password. WARNING: Minimum length of 10 characters
+  ## Defaults to a random 10-character alphanumeric string if not set
+  ##
+  password: ""
+  ## @param discourse.existingSecret Name of an existing secret containing the password (ignores previous password)
+  ## The secret should contain the following key:
+  ## discourse-password
+  ##
+  existingSecret: ""
+  ## @param discourse.email Admin user email of the application
+  ##
+  email: user@example.com
+  ## @param discourse.command Custom command to override image cmd
+  ##
+  command: []
+  ## @param discourse.args Custom args for the custom command
+  ##
+  args: []
+  ## @param discourse.containerSecurityContext Container security context specification
+  ## Example:
+  ## capabilities:
+  ##   drop:
+  ##   - ALL
+  ## readOnlyRootFilesystem: true
+  ## runAsNonRoot: true
+  ## runAsUser: 1000
+  ##
+  containerSecurityContext: {}
+  ## Discourse container's resource requests and limits
+  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
+  ## We usually recommend not to specify default resources and to leave this as a conscious
+  ## choice for the user. This also increases chances charts run on environments with little
+  ## resources, such as Minikube. If you do want to specify resources, uncomment the following
+  ## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+  ## @param discourse.resources.limits The resources limits for the container
+  ## @param discourse.resources.requests The requested resources for the container
+  ##
+  resources:
+    ## Example:
+    ## limits:
+    ##    cpu: 100m
+    ##    memory: 128Mi
+    limits: {}
+    ## Examples:
+    ## requests:
+    ##    cpu: 100m
+    ##    memory: 128Mi
+    requests: {}
+  ## Discourse extra options for liveness probe
+  ## WARNING: Discourse installation process may take up some time and
+  ## setting inappropriate values here may lead to pods failure.
+  ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+  ## @param discourse.livenessProbe.enabled Enable/disable livenessProbe
+  ## @param discourse.livenessProbe.initialDelaySeconds Delay before liveness probe is initiated
+  ## @param discourse.livenessProbe.periodSeconds How often to perform the probe
+  ## @param discourse.livenessProbe.timeoutSeconds When the probe times out
+  ## @param discourse.livenessProbe.failureThreshold Minimum consecutive failures for the probe
+  ## @param discourse.livenessProbe.successThreshold Minimum consecutive successes for the probe
+  ##
+  livenessProbe:
+    enabled: true
+    initialDelaySeconds: 500
+    periodSeconds: 10
+    timeoutSeconds: 5
+    failureThreshold: 6
+    successThreshold: 1
+  ## Discourse extra options for readiness probe
+  ## WARNING: Discourse installation process may take up some time and
+  ## setting inappropriate values here may lead to pods failure.
+  ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+  ## @param discourse.readinessProbe.enabled Enable/disable readinessProbe
+  ## @param discourse.readinessProbe.initialDelaySeconds Delay before readiness probe is initiated
+  ## @param discourse.readinessProbe.periodSeconds How often to perform the probe
+  ## @param discourse.readinessProbe.timeoutSeconds When the probe times out
+  ## @param discourse.readinessProbe.failureThreshold Minimum consecutive failures for the probe
+  ## @param discourse.readinessProbe.successThreshold Minimum consecutive successes for the probe
+  ##
+  readinessProbe:
+    enabled: true
+    initialDelaySeconds: 30
+    periodSeconds: 10
+    timeoutSeconds: 5
+    failureThreshold: 6
+    successThreshold: 1
+  ## @param discourse.customLivenessProbe Custom liveness probe to execute (when the main one is disabled)
+  ##
+  customLivenessProbe: {}
+  ## @param discourse.customReadinessProbe Custom readiness probe to execute (when the main one is disabled)
+  ##
+  customReadinessProbe: {}
+  ## Discourse SMTP settings
+  ## @param discourse.smtp.enabled Enable/disable SMTP
+  ## @param discourse.smtp.host SMTP host name
+  ## @param discourse.smtp.port SMTP port number
+  ## @param discourse.smtp.user SMTP account user name
+  ## @param discourse.smtp.password SMTP account password
+  ## @param discourse.smtp.protocol SMTP protocol (Allowed values: tls, ssl)
+  ## @param discourse.smtp.auth SMTP authentication method
+  ## @param discourse.smtp.existingSecret Name of an existing Kubernetes secret. The secret must have the following key configured: `smtp-password`
+  ##
+  smtp:
+    enabled: false
+    host: ""
+    port: ""
+    user: ""
+    password: ""
+    protocol: ""
+    auth: ""
+    existingSecret: ""
+  ## @param discourse.extraEnvVars An array to add extra env vars
+  ## For example:
+  ## extraEnvVars:
+  ##   discourse:
+  ##   - name: DISCOURSE_ELASTICSEARCH_URL
+  ##     value: test
+  ##
+  extraEnvVars: []
+  ## @param discourse.extraEnvVarsCM Array to add extra configmaps
+  ##
+  extraEnvVarsCM: []
+  ## @param discourse.extraEnvVarsSecret Array to add extra environment variables from a secret
+  ##
+  extraEnvVarsSecret: ""
+  ## @param discourse.extraVolumeMounts Additional volume mounts (used along with `extraVolumes`)
+  ## Example: Mount CA file
+  ## extraVolumeMounts
+  ##   - name: ca-cert
+  ##     subPath: ca_cert
+  ##     mountPath: /path/to/ca_cert
+  ##
+  extraVolumeMounts: []
+  ## @param discourse.skipInstall Do not run the Discourse installation wizard
+  ## Use only in case you are importing an existing database.
+  ##
+  skipInstall: false
+## @param replicaCount Number of Discourse & Sidekiq replicas
+## (Note that you will need ReadWriteMany PVCs for this to work properly)
+##
+replicaCount: 1
+## @param extraVolumes Array of extra volumes to be added deployment. Requires setting `extraVolumeMounts`
+## Example: Add secret volume
+## extraVolumes:
+##  - name: ca-cert
+##    secret:
+##      secretName: ca-cert
+##      items:
+##        - key: ca-cert
+##          path: ca_cert
+##
+extraVolumes: []
+## @param sidecars Attach additional sidecar containers to the pod
+## Example:
+## sidecars:
+##   - name: your-image-name
+##     image: your-image
+##     imagePullPolicy: Always
+##     ports:
+##       - name: portname
+##         containerPort: 1234
+##
+sidecars: []
+## @param initContainers Additional init containers to add to the pods
+##
+## e.g.
+## initContainers:
+##   - name: your-image-name
+##     image: your-image
+##     imagePullPolicy: Always
+##     ports:
+##       - name: portname
+##       containerPort: 1234
+##
+initContainers: []
+## @param serviceAccount.create Whether the service account should be created
+## @param serviceAccount.annotations Annotations to add to the service account
+## @param serviceAccount.name Name to be used for the service account
+##
+serviceAccount:
+  create: false
+  annotations: {}
+  ## If not set and create is true, a name is generated using the fullname template
+  ##
+  name: ""
+## @param podSecurityContext Pod security context specification
+## Example:
+##  fsGroup: 2000
+##
+##
+podSecurityContext: {}
+## @param hostAliases Add deployment host aliases
+## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/
+##
+hostAliases: []
+## Enable persistence using Persistent Volume Claims
+## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
+##
+persistence:
+  ## @param persistence.enabled Whether to enable persistence based on Persistent Volume Claims
+  ##
+  enabled: true
+  ## @param persistence.storageClass discourse & sidekiq data Persistent Volume Storage Class
+  ## If defined, storageClassName: <storageClass>
+  ## If set to "-", storageClassName: "", which disables dynamic provisioning
+  ## If undefined (the default) or set to null, no storageClassName spec is
+  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
+  ##   GKE, AWS & OpenStack)
+  ##
+  storageClass: ""
+  ## @param persistence.existingClaim Use a existing PVC which must be created manually before bound
+  ##
+  existingClaim: ""
+  ## @param persistence.accessMode PVC Access Mode (RWO, ROX, RWX)
+  ##
+  accessMode: ReadWriteOnce
+  ## @param persistence.size Size of the PVC to request
+  ##
+  size: 10Gi
+  ## @param persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template)
+  ## selector:
+  ##   matchLabels:
+  ##     app: my-app
+  selector: {}
+## @param updateStrategy.type Update strategy type. Only really applicable for deployments with RWO PVs attached
+## If replicas = 1, an update can get "stuck", as the previous pod remains attached to the
+## PV, and the "incoming" pod can never start. Changing the strategy to "Recreate" will
+## terminate the single previous pod, so that the new, incoming pod can attach to the PV
+## Example:
+## updateStrategy:
+##  type: RollingUpdate
+##  rollingUpdate:
+##    maxSurge: 25%
+##    maxUnavailable: 25%
+updateStrategy:
+  type: RollingUpdate
+## @param podAnnotations Additional pod annotations
+## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
+##
+podAnnotations: {}
+## @param podLabels Additional pod labels
+## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
+##
+podLabels: {}
+## @param podAffinityPreset Pod affinity preset. Allowed values: soft, hard
+## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
+##
+podAffinityPreset: ""
+## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`
+## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
+##
+podAntiAffinityPreset: soft
+## Node affinity preset
+## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
+## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard`
+## @param nodeAffinityPreset.key Node label key to match Ignored if `affinity` is set.
+## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set.
+##
+nodeAffinityPreset:
+  type: ""
+  ## E.g.
+  ## key: "kubernetes.io/e2e-az-name"
+  ##
+  key: ""
+  ## E.g.
+  ## values:
+  ##   - e2e-az1
+  ##   - e2e-az2
+  ##
+  values: []
+## @param affinity Affinity for pod assignment
+## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
+## Note: podAffinityPreset, podAntiAffinityPreset, and  nodeAffinityPreset will be ignored when it's set
+##
+affinity: {}
+## @param nodeSelector Node labels for pod assignment.
+## Ref: https://kubernetes.io/docs/user-guide/node-selection/
+##
+nodeSelector: {}
+## @param tolerations Tolerations for pod assignment.
+## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
+##
+tolerations: []
+
+## @section Sidekiq parameters
+
+sidekiq:
+  ## @param sidekiq.containerSecurityContext Container security context specification
+  ## capabilities:
+  ##   drop:
+  ##   - ALL
+  ## readOnlyRootFilesystem: true
+  ## runAsNonRoot: true
+  ## runAsUser: 1000
+  ##
+  containerSecurityContext: {}
+  ## @param sidekiq.command Custom command to override image cmd (evaluated as a template)
+  ##
+  command: ['/opt/bitnami/scripts/discourse/entrypoint.sh']
+  ## @param sidekiq.args Custom args for the custom command (evaluated as a template)
+  ##
+  args: ['/opt/bitnami/scripts/discourse-sidekiq/run.sh']
+  ## @param sidekiq.resources Sidekiq container resource requests and limits
+  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
+  ## We usually recommend not to specify default resources and to leave this as a conscious
+  ## choice for the user. This also increases chances charts run on environments with little
+  ## resources, such as Minikube. If you do want to specify resources, uncomment the following
+  ## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+  ##
+  resources: {}
+  ## Sidekiq extra options for liveness probe
+  ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+  ## @param sidekiq.livenessProbe.enabled Enable/disable livenessProbe
+  ## @param sidekiq.livenessProbe.initialDelaySeconds Delay before liveness probe is initiated
+  ## @param sidekiq.livenessProbe.periodSeconds How often to perform the probe
+  ## @param sidekiq.livenessProbe.timeoutSeconds When the probe times out
+  ## @param sidekiq.livenessProbe.failureThreshold Minimum consecutive failures for the probe
+  ## @param sidekiq.livenessProbe.successThreshold Minimum consecutive successes for the probe
+  ##
+  livenessProbe:
+    enabled: true
+    initialDelaySeconds: 500
+    periodSeconds: 10
+    timeoutSeconds: 5
+    failureThreshold: 6
+    successThreshold: 1
+  ## Sidekiq extra options for readiness probe
+  ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+  ## @param sidekiq.readinessProbe.enabled Enable/disable readinessProbe
+  ## @param sidekiq.readinessProbe.initialDelaySeconds Delay before readiness probe is initiated
+  ## @param sidekiq.readinessProbe.periodSeconds How often to perform the probe
+  ## @param sidekiq.readinessProbe.timeoutSeconds When the probe times out
+  ## @param sidekiq.readinessProbe.failureThreshold Minimum consecutive failures for the probe
+  ## @param sidekiq.readinessProbe.successThreshold Minimum consecutive successes for the probe
+  ##
+  readinessProbe:
+    enabled: true
+    initialDelaySeconds: 30
+    periodSeconds: 10
+    timeoutSeconds: 5
+    failureThreshold: 6
+    successThreshold: 1
+  ## @param sidekiq.customLivenessProbe Custom liveness probe to execute (when the main one is disabled)
+  ##
+  customLivenessProbe: {}
+  ## @param sidekiq.customReadinessProbe Custom readiness probe to execute (when the main one is disabled)
+  ##
+  customReadinessProbe: {}
+  ## @param sidekiq.extraEnvVars An array to add extra env vars
+  ## For example:
+  ## extraEnvVars:
+  ##   - name: DISCOURSE_ELASTICSEARCH_URL
+  ##     value: test
+  ##
+  extraEnvVars: []
+  ## @param sidekiq.extraEnvVarsCM Array to add extra configmaps
+  ##
+  extraEnvVarsCM: []
+  ## @param sidekiq.extraEnvVarsSecret Name of the secret that holds extra env vars
+  ##
+  extraEnvVarsSecret: ""
+  ## @param sidekiq.extraVolumeMounts Additional volume mounts
+  ## Example: Mount CA file
+  ## extraVolumeMounts
+  ##   - name: ca-cert
+  ##     subPath: ca_cert
+  ##     mountPath: /path/to/ca_cert
+  ##
+  extraVolumeMounts: []
+
+## @section Volume Permissions parameters
+
+## Init containers parameters:
+## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup
+## values from the securityContext section.
+##
+volumePermissions:
+  ## @param volumePermissions.enabled Enable init container that changes volume permissions in the data directory (for cases where the default k8s `runAsUser` and `fsUser` values do not work)
+  ##
+  enabled: false
+  ## Init containers' resource requests and limits
+  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
+  ## We usually recommend not to specify default resources and to leave this as a conscious
+  ## choice for the user. This also increases chances charts run on environments with little
+  ## resources, such as Minikube. If you do want to specify resources, uncomment the following
+  ## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+  ## @param volumePermissions.resources.limits The resources limits for the init container
+  ## @param volumePermissions.resources.requests The requested resources for the init container
+  ##
+  resources:
+    ## Example:
+    ## limits:
+    ##    cpu: 100m
+    ##    memory: 128Mi
+    limits: {}
+    ## Examples:
+    ## requests:
+    ##    cpu: 100m
+    ##    memory: 128Mi
+    requests: {}
+
+## @section Ingress parameters
+
+## Ingress parameters
+##
+ingress:
+  ## @param ingress.enabled Enable ingress controller resource
+  ##
+  enabled: false
+  ## @param ingress.certManager Add annotations for cert-manager
+  ##
+  certManager: false
+  ## @param ingress.hostname Default host for the ingress resource
+  ##
+  hostname: discourse.local
+  ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set)
+  ##
+  apiVersion: ""
+  ## @param ingress.path Ingress path
+  ##
+  path: /
+  ## @param ingress.pathType Ingress path type
+  ##
+  pathType: ImplementationSpecific
+  ## @param ingress.annotations Ingress annotations done as key:value pairs
+  ## For a full list of possible ingress annotations, please see
+  ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
+  ##
+  ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set
+  ##
+  annotations: {}
+  ## @param ingress.tls Enable TLS configuration for the hostname defined at ingress.hostname parameter
+  ## TLS certificates will be retrieved from a TLS secret with name: {{- printf "%s-tls" .Values.ingress.hostname }}
+  ## You can use the ingress.secrets parameter to create this TLS secret or relay on cert-manager to create it
+  ##
+  tls: false
+  ## @param ingress.extraHosts The list of additional hostnames to be covered with this ingress record.
+  ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array
+  ## extraHosts:
+  ## - name: discourse.local
+  ##   path: /
+  extraHosts: []
+  ## @param ingress.extraTls The tls configuration for additional hostnames to be covered with this ingress record.
+  ## see: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls
+  ## extraTls:
+  ## - hosts:
+  ##     - discourse.local
+  ##   secretName: discourse.local-tls
+  extraTls: []
+  ## @param ingress.secrets If you're providing your own certificates, please use this to add the certificates as secrets
+  ## key and certificate should start with -----BEGIN CERTIFICATE----- or
+  ## -----BEGIN RSA PRIVATE KEY-----
+  ##
+  ## name should line up with a tlsSecret set further up
+  ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set
+  ##
+  ## It is also possible to create and manage the certificates outside of this helm chart
+  ## Please see README.md for more information
+  ## Example:
+  ## - name: discourse.local-tls
+  ##   key:
+  ##   certificate:
+  secrets: []
+
+## @section Database parameters
+
+## PostgreSQL chart configuration
+## https://github.com/bitnami/charts/blob/master/bitnami/postgresql/values.yaml
+##
+postgresql:
+  ## @param postgresql.enabled Deploy PostgreSQL container(s)
+  ##
+  enabled: true
+  ## @param postgresql.postgresqlUsername PostgreSQL user to create (used by Discourse). Has superuser privileges if username is `postgres`.
+  ## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run
+  ##
+  postgresqlUsername: bn_discourse
+  ## @param postgresql.postgresqlPassword PostgreSQL password
+  ## Defaults to a random 10-character alphanumeric string if not set
+  ## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run
+  ##
+  postgresqlPassword: ""
+  ## @param postgresql.postgresqlPostgresPassword PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`)
+  ## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!)
+  ##
+  postgresqlPostgresPassword: 'bitnami'
+  ## @param postgresql.existingSecret Name of existing secret object
+  ## The secret should contain the following keys:
+  ## postgresql-postgres-password (for root user)
+  ## postgresql-password (for the unprivileged user)
+  ##
+  existingSecret: ""
+  ## @param postgresql.postgresqlDatabase Name of the database to create
+  ## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run
+  ##
+  postgresqlDatabase: bitnami_application
+  ## @param postgresql.persistence.enabled Enable database persistence using PVC
+  ##
+  persistence:
+    enabled: true
+## External database configuration
+##
+externalDatabase:
+  ## @param externalDatabase.host Host of the external database
+  ##
+  host: ""
+  ## @param externalDatabase.port Database port number (when using an external db)
+  ##
+  port: 5432
+  ## @param externalDatabase.user Non-root PostgreSQL username (when using an external db)
+  ##
+  user: bn_discourse
+  ## @param externalDatabase.password Password for the above username (when using an external db)
+  ##
+  password: ""
+  ## @param externalDatabase.create PostgreSQL create user/database
+  ## If true it will add POSTGRESQL_CLIENT_* env vars to the deployment which will create the PostgreSQL user & database using the provided admin credentials
+  ##
+  create: true
+  ## @param externalDatabase.postgresqlPostgresUser PostgreSQL admin user, used during the installation stage (when using an external db)
+  ##
+  postgresqlPostgresUser: ""
+  ## @param externalDatabase.postgresqlPostgresPassword PostgreSQL admin password used in the installation stage (when using an external db)
+  ##
+  postgresqlPostgresPassword: ""
+  ## @param externalDatabase.existingSecret Name of existing secret object
+  ## The secret should contain the following keys:
+  ## postgresql-postgres-password (for root user)
+  ## postgresql-password (for the unprivileged user)
+  ##
+  existingSecret: ""
+  ## @param externalDatabase.database Name of the existing database (when using an external db)
+  ##
+  database: bitnami_application
+
+## @section Redis&trade; parameters
+
+## Redis&trade; chart configuration
+## https://github.com/bitnami/charts/blob/master/bitnami/redis/values.yaml
+##
+redis:
+  ## @param redis.enabled Whether to deploy a redis server to satisfy the applications requirements. To use an external redis instance set this to false and configure the externalRedis parameters
+  ##
+  enabled: true
+  ## Use password authentication
+  ## @param redis.auth.enabled Use password authentication
+  ## @param redis.auth.password Redis&trade; password (both master and replica)
+  ## @param redis.auth.existingSecret Name of an existing Kubernetes secret object containing the password
+  ## @param redis.auth.existingSecretPasswordKey Name of the key pointing to the password in your Kubernetes secret
+  ##
+  auth:
+    enabled: false
+    ## Defaults to a random 10-character alphanumeric string if not set and auth.enabled is true.
+    ## It should always be set using the password value or in the existingSecret to avoid issues
+    ## with Discourse.
+    ## The password value is ignored if existingSecret is set
+    password: ""
+    existingSecret: ""
+    existingSecretPasswordKey: 'redis-password'
+  ## @param redis.architecture Cluster settings
+  ##
+  architecture: standalone
+  ## Redis&trade; Master parameters
+  ## @param redis.master.persistence.enabled Enable database persistence using PVC
+  ##
+  master:
+    persistence:
+      enabled: true
+## External Redis&trade;
+## @param externalRedis.host Host of the external database
+## @param externalRedis.port Database port number
+## @param externalRedis.password Password for the external Redis. Ignored if existingSecret is set
+## @param externalRedis.existingSecret Name of an existing Kubernetes secret object containing the password
+## @param externalRedis.existingSecretPasswordKey Name of the key pointing to the password in your Kubernetes secret
+##
+externalRedis:
+  host: ""
+  port: 6379
+  password: ""
+  existingSecret: ""
+  existingSecretPasswordKey: 'redis-password'