Compare commits

...

1 Commits

Author SHA1 Message Date
Bhagya Amarasinghe 9d0169ce81 fix: use Valkey for bundled Helm Redis 2026-05-21 13:03:14 +05:30
13 changed files with 353 additions and 21 deletions
+2 -5
View File
@@ -2,14 +2,11 @@ dependencies:
- name: postgresql
repository: oci://registry-1.docker.io/bitnamicharts
version: 16.4.16
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
version: 20.11.2
- name: gateway-helm
repository: oci://docker.io/envoyproxy
version: v1.7.1
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
version: 20.11.2
digest: sha256:d93a29cb9cbef513db410ded5aa199f219c5b25ce1870e1e049dc470acc34235
generated: "2026-04-08T00:33:09.875832+05:30"
digest: sha256:078652b37649ba5bb72f7463709356c08f464cb989270b97d095b8243c0e58b9
generated: "2026-05-21T12:52:44.141547+05:30"
+2 -6
View File
@@ -1,6 +1,6 @@
apiVersion: v2
name: formbricks
description: A Helm chart for Formbricks with PostgreSQL, Redis
description: A Helm chart for Formbricks with PostgreSQL, Valkey
type: application
@@ -15,7 +15,7 @@ icon: https://formbricks.com/favicon.ico
keywords:
- formbricks
- postgresql
- redis
- valkey
home: https://formbricks.com/docs/self-hosting/setup/kubernetes
maintainers:
@@ -27,10 +27,6 @@ dependencies:
version: "16.4.16"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgresql.enabled
- name: redis
version: 20.11.2
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: redis.enabled
- name: gateway-helm
alias: envoy
version: "v1.7.1"
+24 -4
View File
@@ -2,7 +2,7 @@
![Version: 0.0.0-dev](https://img.shields.io/badge/Version-0.0.0--dev-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 5.0.0-rc.1](https://img.shields.io/badge/AppVersion-5.0.0--rc.1-informational?style=flat-square)
A Helm chart for Formbricks with PostgreSQL, Redis
A Helm chart for Formbricks with PostgreSQL, Valkey
**Homepage:** <https://formbricks.com/docs/self-hosting/setup/kubernetes>
@@ -17,9 +17,8 @@ A Helm chart for Formbricks with PostgreSQL, Redis
| Repository | Name | Version |
| ---------------------------------------- | ------------ | ------- |
| oci://registry-1.docker.io/bitnamicharts | postgresql | 16.4.16 |
| oci://registry-1.docker.io/bitnamicharts | redis | 20.11.2 |
| oci://docker.io/envoyproxy | gateway-helm | v1.7.1 |
| oci://registry-1.docker.io/bitnamicharts | redis | 20.11.2 |
| oci://registry-1.docker.io/bitnamicharts | envoyRedis | 20.11.2 |
## Envoy bundle modes
@@ -32,7 +31,7 @@ rate limiting.
Gateway API CRDs plus an Envoy Gateway controller compatible with
`envoy.config.envoyGateway.gateway.controllerName`.
- `envoyRedis.enabled=true` deploys a dedicated Redis replication + Sentinel bundle for Envoy RLS. It is intentionally
separate from the existing app `redis` dependency.
separate from the bundled app Valkey deployment.
- The bundled controller reads its Redis backend from `envoy.config.envoyGateway.rateLimit.backend.redis.url`.
If you enable Redis authentication or override `envoyRedis.fullnameOverride`, set that URL explicitly so the
controller points at the correct backend.
@@ -289,7 +288,28 @@ Autoscaling is opt-in for Hub API, Hub worker, and the embeddings runtime. If yo
| redis.enabled | bool | `true` | |
| redis.externalRedisUrl | string | `""` | |
| redis.fullnameOverride | string | `"formbricks-redis"` | |
| redis.image.digest | string | `"sha256:12ba4f45a7c3e1d0f076acd616cb230834e75a77e8516dde382720af32832d6d"` | |
| redis.image.pullPolicy | string | `"IfNotPresent"` | |
| redis.image.repository | string | `"valkey/valkey"` | |
| redis.image.tag | string | `""` | |
| redis.master.affinity | object | `{}` | |
| redis.master.containerSecurityContext | object | `{}` | |
| redis.master.nodeSelector | object | `{}` | |
| redis.master.pdb.enabled | bool | `true` | |
| redis.master.pdb.maxUnavailable | int | `1` | |
| redis.master.pdb.minAvailable | string | `""` | |
| redis.master.persistence.accessModes[0] | string | `"ReadWriteOnce"` | |
| redis.master.persistence.enabled | bool | `true` | |
| redis.master.persistence.size | string | `"8Gi"` | |
| redis.master.persistence.storageClass | string | `""` | |
| redis.master.podAnnotations | object | `{}` | |
| redis.master.podSecurityContext | object | `{}` | |
| redis.master.resources.limits.cpu | string | `"150m"` | |
| redis.master.resources.limits.memory | string | `"192Mi"` | |
| redis.master.resources.requests.cpu | string | `"100m"` | |
| redis.master.resources.requests.memory | string | `"128Mi"` | |
| redis.master.tolerations | list | `[]` | |
| redis.master.topologySpreadConstraints | list | `[]` | |
| redis.networkPolicy.enabled | bool | `false` | |
| secret.enabled | bool | `true` | |
| service.additionalLabels | object | `{}` | |
+1 -1
View File
@@ -69,7 +69,7 @@ Redis Access:
kubectl get secret --namespace {{ .Release.Namespace }} {{ include "formbricks.name" . }}-app-secrets -o jsonpath="{.data.REDIS_PASSWORD}" | base64 --decode
```
Connection details:
- **Host**: `{{ include "formbricks.name" . }}-redis-master`
- **Host**: `{{ include "formbricks.redisMasterName" . }}`
- **Port**: `6379`
{{- else if .Values.redis.externalRedisUrl }}
You're using an external Redis instance.
+20
View File
@@ -125,6 +125,26 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
{{- printf "%s-app-secrets" (include "formbricks.name" .) -}}
{{- end }}
{{- define "formbricks.redisName" -}}
{{- .Values.redis.fullnameOverride | default (printf "%s-redis" (include "formbricks.name" .)) | trunc 63 | trimSuffix "-" -}}
{{- end }}
{{- define "formbricks.redisMasterName" -}}
{{- printf "%s-master" (include "formbricks.redisName" .) | trunc 63 | trimSuffix "-" -}}
{{- end }}
{{- define "formbricks.redisHeadlessName" -}}
{{- printf "%s-headless" (include "formbricks.redisName" .) | trunc 63 | trimSuffix "-" -}}
{{- end }}
{{- define "formbricks.redisImage" -}}
{{- if .Values.redis.image.digest -}}
{{- printf "%s@%s" .Values.redis.image.repository .Values.redis.image.digest -}}
{{- else -}}
{{- printf "%s:%s" .Values.redis.image.repository .Values.redis.image.tag -}}
{{- end -}}
{{- end }}
{{- define "formbricks.hubSecretName" -}}
{{- default (include "formbricks.appSecretName" .) .Values.hub.existingSecret -}}
{{- end }}
@@ -0,0 +1,17 @@
{{- if .Values.redis.enabled }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "formbricks.redisName" . }}-configuration
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
data:
valkey.conf: |-
{{ .Values.redis.commonConfiguration | nindent 4 }}
{{- end }}
@@ -0,0 +1,28 @@
{{- if and .Values.redis.enabled .Values.redis.networkPolicy.enabled }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "formbricks.redisMasterName" . }}
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
ports:
- port: redis
protocol: TCP
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.redis.enabled .Values.redis.master.pdb.enabled }}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "formbricks.redisMasterName" . }}
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
spec:
{{- if .Values.redis.master.pdb.minAvailable }}
minAvailable: {{ .Values.redis.master.pdb.minAvailable }}
{{- else }}
maxUnavailable: {{ .Values.redis.master.pdb.maxUnavailable | default 1 }}
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
{{- end }}
@@ -0,0 +1,50 @@
{{- if .Values.redis.enabled }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "formbricks.redisHeadlessName" . }}
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: true
selector:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
ports:
- name: redis
port: 6379
targetPort: redis
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "formbricks.redisMasterName" . }}
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
ports:
- name: redis
port: 6379
targetPort: redis
protocol: TCP
{{- end }}
@@ -0,0 +1,147 @@
{{- if .Values.redis.enabled }}
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "formbricks.redisMasterName" . }}
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
spec:
replicas: 1
serviceName: {{ include "formbricks.redisHeadlessName" . }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
annotations:
checksum/config: {{ include (print $.Template.BasePath "/redis-configmap.yaml") . | sha256sum }}
{{- with .Values.redis.master.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.redis.master.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.redis.master.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.redis.master.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.redis.master.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.redis.master.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: valkey
image: {{ include "formbricks.redisImage" . }}
imagePullPolicy: {{ .Values.redis.image.pullPolicy }}
{{- with .Values.redis.master.containerSecurityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
command:
- /bin/sh
- -c
- |
set -eu
{{- if .Values.redis.auth.enabled }}
exec valkey-server /etc/valkey/valkey.conf --requirepass "$VALKEY_PASSWORD"
{{- else }}
exec valkey-server /etc/valkey/valkey.conf
{{- end }}
ports:
- name: redis
containerPort: 6379
protocol: TCP
{{- if .Values.redis.auth.enabled }}
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.redis.auth.existingSecret | default (include "formbricks.appSecretName" .) }}
key: {{ .Values.redis.auth.existingSecretPasswordKey | default "REDIS_PASSWORD" }}
- name: REDISCLI_AUTH
valueFrom:
secretKeyRef:
name: {{ .Values.redis.auth.existingSecret | default (include "formbricks.appSecretName" .) }}
key: {{ .Values.redis.auth.existingSecretPasswordKey | default "REDIS_PASSWORD" }}
{{- end }}
livenessProbe:
exec:
command:
- /bin/sh
- -c
- valkey-cli ping | grep -q PONG
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 5
readinessProbe:
exec:
command:
- /bin/sh
- -c
- valkey-cli ping | grep -q PONG
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 5
{{- with .Values.redis.master.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: redis-config
mountPath: /etc/valkey
readOnly: true
- name: redis-data
mountPath: /data
volumes:
- name: redis-config
configMap:
name: {{ include "formbricks.redisName" . }}-configuration
{{- if .Values.redis.master.persistence.enabled }}
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data
labels:
helm.sh/chart: {{ include "formbricks.chart" . }}
app.kubernetes.io/name: {{ include "formbricks.redisName" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: redis
spec:
accessModes:
{{- toYaml .Values.redis.master.persistence.accessModes | nindent 10 }}
{{- with .Values.redis.master.persistence.storageClass }}
storageClassName: {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.redis.master.persistence.size | quote }}
{{- else }}
- name: redis-data
emptyDir: {}
{{- end }}
{{- end }}
@@ -0,0 +1,3 @@
{{- if and .Values.redis.enabled (ne (.Values.redis.architecture | toString) "standalone") -}}
{{- fail "redis.architecture currently supports only standalone with the bundled Valkey deployment. Use redis.externalRedisUrl and redis.enabled=false for external HA Redis/Valkey." -}}
{{- end -}}
+5 -3
View File
@@ -20,8 +20,10 @@ data:
{{- if .Values.formbricks.publicUrl }}
PUBLIC_URL: {{ .Values.formbricks.publicUrl | b64enc }}
{{- end }}
{{- if .Values.redis.enabled }}
REDIS_URL: {{ printf "redis://:%s@formbricks-redis-master:6379" $redisPassword | b64enc }}
{{- if and .Values.redis.enabled .Values.redis.auth.enabled }}
REDIS_URL: {{ printf "redis://:%s@%s:6379" $redisPassword (include "formbricks.redisMasterName" .) | b64enc }}
{{- else if .Values.redis.enabled }}
REDIS_URL: {{ printf "redis://%s:6379" (include "formbricks.redisMasterName" .) | b64enc }}
{{- else }}
REDIS_URL: {{ .Values.redis.externalRedisUrl | b64enc }}
{{- end }}
@@ -39,7 +41,7 @@ data:
{{- if and (.Values.enterprise.licenseKey) (ne .Values.enterprise.licenseKey "") }}
ENTERPRISE_LICENSE_KEY: {{ .Values.enterprise.licenseKey | b64enc }}
{{- end }}
{{- if .Values.redis.enabled }}
{{- if and .Values.redis.enabled .Values.redis.auth.enabled }}
REDIS_PASSWORD: {{ $redisPassword | b64enc }}
{{- end }}
{{- if .Values.postgresql.enabled }}
+29 -2
View File
@@ -513,15 +513,20 @@ envoyRedis:
enabled: false
##########################################################
# Redis Configuration
# Valkey Configuration
##########################################################
redis:
enabled: true # Enable/disable Redis
enabled: true # Enable/disable bundled Valkey
# Use this to point Formbricks jobs and cache traffic at an existing Redis/Valkey deployment.
# External Redis instances must also be configured with `maxmemory-policy noeviction`
# in their redis.conf/valkey.conf (or equivalent managed-service setting) to avoid BullMQ job loss.
externalRedisUrl: ""
fullnameOverride: "formbricks-redis"
image:
repository: "valkey/valkey"
tag: ""
digest: "sha256:12ba4f45a7c3e1d0f076acd616cb230834e75a77e8516dde382720af32832d6d"
pullPolicy: IfNotPresent
architecture: standalone
commonConfiguration: |-
appendonly yes
@@ -534,8 +539,30 @@ redis:
networkPolicy:
enabled: false
master:
resources:
limits:
cpu: 150m
memory: 192Mi
requests:
cpu: 100m
memory: 128Mi
podSecurityContext: {}
containerSecurityContext: {}
podAnnotations: {}
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
persistence:
enabled: true
size: 8Gi
storageClass: ""
accessModes:
- ReadWriteOnce
pdb:
enabled: true
minAvailable: ""
maxUnavailable: 1
##########################################################
# Service Monitor to collect Prometheus metrices