mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-26 09:51:48 -05:00
Compare commits
1 Commits
feat/workf
...
epic/v5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81272b96e1 |
@@ -38,6 +38,15 @@ LOG_LEVEL=info
|
||||
|
||||
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/formbricks?schema=public'
|
||||
|
||||
#################
|
||||
# HUB (DEV) #
|
||||
#################
|
||||
# The dev stack (pnpm db:up / pnpm go) runs Formbricks Hub on port 8080.
|
||||
# Set explicitly to avoid confusion; override as needed when using docker-compose.dev.yml.
|
||||
HUB_API_KEY=dev-api-key
|
||||
HUB_API_URL=http://localhost:8080
|
||||
HUB_DATABASE_URL=postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable
|
||||
|
||||
################
|
||||
# MAIL SETUP #
|
||||
################
|
||||
|
||||
@@ -40,6 +40,8 @@ export const GITHUB_ID = env.GITHUB_ID;
|
||||
export const GITHUB_SECRET = env.GITHUB_SECRET;
|
||||
export const GOOGLE_CLIENT_ID = env.GOOGLE_CLIENT_ID;
|
||||
export const GOOGLE_CLIENT_SECRET = env.GOOGLE_CLIENT_SECRET;
|
||||
export const HUB_API_URL = env.HUB_API_URL;
|
||||
export const HUB_API_KEY = env.HUB_API_KEY;
|
||||
|
||||
export const AZUREAD_CLIENT_ID = env.AZUREAD_CLIENT_ID;
|
||||
export const AZUREAD_CLIENT_SECRET = env.AZUREAD_CLIENT_SECRET;
|
||||
|
||||
@@ -33,6 +33,8 @@ export const env = createEnv({
|
||||
GOOGLE_SHEETS_REDIRECT_URL: z.string().optional(),
|
||||
HTTP_PROXY: z.url().optional(),
|
||||
HTTPS_PROXY: z.url().optional(),
|
||||
HUB_API_URL: z.url(),
|
||||
HUB_API_KEY: z.string().optional(),
|
||||
IMPRINT_URL: z
|
||||
.url()
|
||||
.optional()
|
||||
@@ -159,6 +161,8 @@ export const env = createEnv({
|
||||
GOOGLE_SHEETS_REDIRECT_URL: process.env.GOOGLE_SHEETS_REDIRECT_URL,
|
||||
HTTP_PROXY: process.env.HTTP_PROXY,
|
||||
HTTPS_PROXY: process.env.HTTPS_PROXY,
|
||||
HUB_API_URL: process.env.HUB_API_URL,
|
||||
HUB_API_KEY: process.env.HUB_API_KEY,
|
||||
IMPRINT_URL: process.env.IMPRINT_URL,
|
||||
IMPRINT_ADDRESS: process.env.IMPRINT_ADDRESS,
|
||||
INVITE_DISABLED: process.env.INVITE_DISABLED,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# formbricks
|
||||
|
||||
 
|
||||
  
|
||||
|
||||
A Helm chart for Formbricks with PostgreSQL, Redis
|
||||
|
||||
@@ -8,150 +8,178 @@ A Helm chart for Formbricks with PostgreSQL, Redis
|
||||
|
||||
## Maintainers
|
||||
|
||||
| Name | Email | Url |
|
||||
| ---------- | --------------------- | --- |
|
||||
| Formbricks | <info@formbricks.com> | |
|
||||
| Name | Email | Url |
|
||||
| ---- | ------ | --- |
|
||||
| Formbricks | <info@formbricks.com> | |
|
||||
|
||||
## Requirements
|
||||
|
||||
| Repository | Name | Version |
|
||||
| ---------------------------------------- | ---------- | ------- |
|
||||
| Repository | Name | Version |
|
||||
|------------|------|---------|
|
||||
| oci://registry-1.docker.io/bitnamicharts | postgresql | 16.4.16 |
|
||||
| oci://registry-1.docker.io/bitnamicharts | redis | 20.11.2 |
|
||||
| oci://registry-1.docker.io/bitnamicharts | redis | 20.11.2 |
|
||||
|
||||
## Values
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
| ------------------------------------------------------------------ | ------ | --------------------------------- | ----------- |
|
||||
| autoscaling.additionalLabels | object | `{}` | |
|
||||
| autoscaling.annotations | object | `{}` | |
|
||||
| autoscaling.enabled | bool | `true` | |
|
||||
| autoscaling.maxReplicas | int | `10` | |
|
||||
| autoscaling.metrics[0].resource.name | string | `"cpu"` | |
|
||||
| autoscaling.metrics[0].resource.target.averageUtilization | int | `60` | |
|
||||
| autoscaling.metrics[0].resource.target.type | string | `"Utilization"` | |
|
||||
| autoscaling.metrics[0].type | string | `"Resource"` | |
|
||||
| autoscaling.metrics[1].resource.name | string | `"memory"` | |
|
||||
| autoscaling.metrics[1].resource.target.averageUtilization | int | `60` | |
|
||||
| autoscaling.metrics[1].resource.target.type | string | `"Utilization"` | |
|
||||
| autoscaling.metrics[1].type | string | `"Resource"` | |
|
||||
| autoscaling.minReplicas | int | `1` | |
|
||||
| componentOverride | string | `""` | |
|
||||
| cronJob.enabled | bool | `false` | |
|
||||
| cronJob.jobs | object | `{}` | |
|
||||
| deployment.additionalLabels | object | `{}` | |
|
||||
| deployment.additionalPodAnnotations | object | `{}` | |
|
||||
| deployment.additionalPodLabels | object | `{}` | |
|
||||
| deployment.affinity | object | `{}` | |
|
||||
| deployment.annotations | object | `{}` | |
|
||||
| deployment.args | list | `[]` | |
|
||||
| deployment.command | list | `[]` | |
|
||||
| deployment.containerSecurityContext.readOnlyRootFilesystem | bool | `true` | |
|
||||
| deployment.containerSecurityContext.runAsNonRoot | bool | `true` | |
|
||||
| deployment.env.EMAIL_VERIFICATION_DISABLED.value | string | `"1"` | |
|
||||
| deployment.env.PASSWORD_RESET_DISABLED.value | string | `"1"` | |
|
||||
| deployment.envFrom | string | `nil` | |
|
||||
| deployment.image.digest | string | `""` | |
|
||||
| deployment.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| deployment.image.repository | string | `"ghcr.io/formbricks/formbricks"` | |
|
||||
| deployment.imagePullSecrets | string | `""` | |
|
||||
| deployment.nodeSelector | object | `{}` | |
|
||||
| deployment.ports.http.containerPort | int | `3000` | |
|
||||
| deployment.ports.http.exposed | bool | `true` | |
|
||||
| deployment.ports.http.protocol | string | `"TCP"` | |
|
||||
| deployment.ports.metrics.containerPort | int | `9464` | |
|
||||
| deployment.ports.metrics.exposed | bool | `true` | |
|
||||
| deployment.ports.metrics.protocol | string | `"TCP"` | |
|
||||
| deployment.probes.livenessProbe.failureThreshold | int | `5` | |
|
||||
| deployment.probes.livenessProbe.httpGet.path | string | `"/health"` | |
|
||||
| deployment.probes.livenessProbe.httpGet.port | int | `3000` | |
|
||||
| deployment.probes.livenessProbe.initialDelaySeconds | int | `10` | |
|
||||
| deployment.probes.livenessProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.livenessProbe.successThreshold | int | `1` | |
|
||||
| deployment.probes.livenessProbe.timeoutSeconds | int | `5` | |
|
||||
| deployment.probes.readinessProbe.failureThreshold | int | `5` | |
|
||||
| deployment.probes.readinessProbe.httpGet.path | string | `"/health"` | |
|
||||
| deployment.probes.readinessProbe.httpGet.port | int | `3000` | |
|
||||
| deployment.probes.readinessProbe.initialDelaySeconds | int | `10` | |
|
||||
| deployment.probes.readinessProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.readinessProbe.successThreshold | int | `1` | |
|
||||
| deployment.probes.readinessProbe.timeoutSeconds | int | `5` | |
|
||||
| deployment.probes.startupProbe.failureThreshold | int | `30` | |
|
||||
| deployment.probes.startupProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.startupProbe.tcpSocket.port | int | `3000` | |
|
||||
| deployment.reloadOnChange | bool | `false` | |
|
||||
| deployment.replicas | int | `1` | |
|
||||
| deployment.resources.limits.memory | string | `"2Gi"` | |
|
||||
| deployment.resources.requests.cpu | string | `"1"` | |
|
||||
| deployment.resources.requests.memory | string | `"1Gi"` | |
|
||||
| deployment.revisionHistoryLimit | int | `2` | |
|
||||
| deployment.securityContext | object | `{}` | |
|
||||
| deployment.strategy.type | string | `"RollingUpdate"` | |
|
||||
| deployment.tolerations | list | `[]` | |
|
||||
| deployment.topologySpreadConstraints | list | `[]` | |
|
||||
| enterprise.enabled | bool | `false` | |
|
||||
| enterprise.licenseKey | string | `""` | |
|
||||
| externalSecret.enabled | bool | `false` | |
|
||||
| externalSecret.files | object | `{}` | |
|
||||
| externalSecret.refreshInterval | string | `"1h"` | |
|
||||
| externalSecret.secretStore.kind | string | `"ClusterSecretStore"` | |
|
||||
| externalSecret.secretStore.name | string | `"aws-secrets-manager"` | |
|
||||
| ingress.annotations | object | `{}` | |
|
||||
| ingress.enabled | bool | `false` | |
|
||||
| ingress.hosts[0].host | string | `"k8s.formbricks.com"` | |
|
||||
| ingress.hosts[0].paths[0].path | string | `"/"` | |
|
||||
| ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | |
|
||||
| ingress.hosts[0].paths[0].serviceName | string | `"formbricks"` | |
|
||||
| ingress.ingressClassName | string | `"alb"` | |
|
||||
| nameOverride | string | `""` | |
|
||||
| partOfOverride | string | `""` | |
|
||||
| postgresql.auth.database | string | `"formbricks"` | |
|
||||
| postgresql.auth.existingSecret | string | `"formbricks-app-secrets"` | |
|
||||
| postgresql.auth.secretKeys.adminPasswordKey | string | `"POSTGRES_ADMIN_PASSWORD"` | |
|
||||
| postgresql.auth.secretKeys.userPasswordKey | string | `"POSTGRES_USER_PASSWORD"` | |
|
||||
| postgresql.auth.username | string | `"formbricks"` | |
|
||||
| postgresql.enabled | bool | `true` | |
|
||||
| postgresql.externalDatabaseUrl | string | `""` | |
|
||||
| postgresql.fullnameOverride | string | `"formbricks-postgresql"` | |
|
||||
| postgresql.global.security.allowInsecureImages | bool | `true` | |
|
||||
| postgresql.image.repository | string | `"pgvector/pgvector"` | |
|
||||
| postgresql.image.tag | string | `"0.8.0-pg17"` | |
|
||||
| postgresql.primary.containerSecurityContext.enabled | bool | `true` | |
|
||||
| postgresql.primary.containerSecurityContext.readOnlyRootFilesystem | bool | `false` | |
|
||||
| postgresql.primary.containerSecurityContext.runAsUser | int | `1001` | |
|
||||
| postgresql.primary.networkPolicy.enabled | bool | `false` | |
|
||||
| postgresql.primary.persistence.enabled | bool | `true` | |
|
||||
| postgresql.primary.persistence.size | string | `"10Gi"` | |
|
||||
| postgresql.primary.podSecurityContext.enabled | bool | `true` | |
|
||||
| postgresql.primary.podSecurityContext.fsGroup | int | `1001` | |
|
||||
| postgresql.primary.podSecurityContext.runAsUser | int | `1001` | |
|
||||
| rbac.enabled | bool | `false` | |
|
||||
| rbac.serviceAccount.additionalLabels | object | `{}` | |
|
||||
| rbac.serviceAccount.annotations | object | `{}` | |
|
||||
| rbac.serviceAccount.enabled | bool | `false` | |
|
||||
| rbac.serviceAccount.name | string | `""` | |
|
||||
| redis.architecture | string | `"standalone"` | |
|
||||
| redis.auth.enabled | bool | `true` | |
|
||||
| redis.auth.existingSecret | string | `"formbricks-app-secrets"` | |
|
||||
| redis.auth.existingSecretPasswordKey | string | `"REDIS_PASSWORD"` | |
|
||||
| redis.enabled | bool | `true` | |
|
||||
| redis.externalRedisUrl | string | `""` | |
|
||||
| redis.fullnameOverride | string | `"formbricks-redis"` | |
|
||||
| redis.master.persistence.enabled | bool | `true` | |
|
||||
| redis.networkPolicy.enabled | bool | `false` | |
|
||||
| secret.enabled | bool | `true` | |
|
||||
| service.additionalLabels | object | `{}` | |
|
||||
| service.annotations | object | `{}` | |
|
||||
| service.enabled | bool | `true` | |
|
||||
| service.ports | list | `[]` | |
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
| serviceMonitor.additionalLabels | string | `nil` | |
|
||||
| serviceMonitor.annotations | string | `nil` | |
|
||||
| serviceMonitor.enabled | bool | `true` | |
|
||||
| serviceMonitor.endpoints[0].interval | string | `"5s"` | |
|
||||
| serviceMonitor.endpoints[0].path | string | `"/metrics"` | |
|
||||
| serviceMonitor.endpoints[0].port | string | `"metrics"` | |
|
||||
|
||||
---
|
||||
|
||||
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| autoscaling.additionalLabels | object | `{}` | |
|
||||
| autoscaling.annotations | object | `{}` | |
|
||||
| autoscaling.behavior.scaleDown.policies[0].periodSeconds | int | `120` | |
|
||||
| autoscaling.behavior.scaleDown.policies[0].type | string | `"Pods"` | |
|
||||
| autoscaling.behavior.scaleDown.policies[0].value | int | `1` | |
|
||||
| autoscaling.behavior.scaleDown.stabilizationWindowSeconds | int | `300` | |
|
||||
| autoscaling.behavior.scaleUp.policies[0].periodSeconds | int | `60` | |
|
||||
| autoscaling.behavior.scaleUp.policies[0].type | string | `"Pods"` | |
|
||||
| autoscaling.behavior.scaleUp.policies[0].value | int | `2` | |
|
||||
| autoscaling.behavior.scaleUp.stabilizationWindowSeconds | int | `60` | |
|
||||
| autoscaling.enabled | bool | `true` | |
|
||||
| autoscaling.maxReplicas | int | `10` | |
|
||||
| autoscaling.metrics[0].resource.name | string | `"cpu"` | |
|
||||
| autoscaling.metrics[0].resource.target.averageUtilization | int | `60` | |
|
||||
| autoscaling.metrics[0].resource.target.type | string | `"Utilization"` | |
|
||||
| autoscaling.metrics[0].type | string | `"Resource"` | |
|
||||
| autoscaling.metrics[1].resource.name | string | `"memory"` | |
|
||||
| autoscaling.metrics[1].resource.target.averageUtilization | int | `60` | |
|
||||
| autoscaling.metrics[1].resource.target.type | string | `"Utilization"` | |
|
||||
| autoscaling.metrics[1].type | string | `"Resource"` | |
|
||||
| autoscaling.minReplicas | int | `1` | |
|
||||
| componentOverride | string | `""` | |
|
||||
| deployment.additionalLabels | object | `{}` | |
|
||||
| deployment.additionalPodAnnotations | object | `{}` | |
|
||||
| deployment.additionalPodLabels | object | `{}` | |
|
||||
| deployment.affinity | object | `{}` | |
|
||||
| deployment.annotations | object | `{}` | |
|
||||
| deployment.args | list | `[]` | |
|
||||
| deployment.command | list | `[]` | |
|
||||
| deployment.containerSecurityContext.readOnlyRootFilesystem | bool | `true` | |
|
||||
| deployment.containerSecurityContext.runAsNonRoot | bool | `true` | |
|
||||
| deployment.env | object | `{}` | |
|
||||
| deployment.envFrom | string | `nil` | |
|
||||
| deployment.image.digest | string | `""` | |
|
||||
| deployment.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| deployment.image.repository | string | `"ghcr.io/formbricks/formbricks"` | |
|
||||
| deployment.image.tag | string | `""` | |
|
||||
| deployment.imagePullSecrets | string | `""` | |
|
||||
| deployment.nodeSelector | object | `{}` | |
|
||||
| deployment.ports.http.containerPort | int | `3000` | |
|
||||
| deployment.ports.http.exposed | bool | `true` | |
|
||||
| deployment.ports.http.protocol | string | `"TCP"` | |
|
||||
| deployment.ports.metrics.containerPort | int | `9464` | |
|
||||
| deployment.ports.metrics.exposed | bool | `true` | |
|
||||
| deployment.ports.metrics.protocol | string | `"TCP"` | |
|
||||
| deployment.probes.livenessProbe.failureThreshold | int | `5` | |
|
||||
| deployment.probes.livenessProbe.httpGet.path | string | `"/health"` | |
|
||||
| deployment.probes.livenessProbe.httpGet.port | int | `3000` | |
|
||||
| deployment.probes.livenessProbe.initialDelaySeconds | int | `10` | |
|
||||
| deployment.probes.livenessProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.livenessProbe.successThreshold | int | `1` | |
|
||||
| deployment.probes.livenessProbe.timeoutSeconds | int | `5` | |
|
||||
| deployment.probes.readinessProbe.failureThreshold | int | `5` | |
|
||||
| deployment.probes.readinessProbe.httpGet.path | string | `"/health"` | |
|
||||
| deployment.probes.readinessProbe.httpGet.port | int | `3000` | |
|
||||
| deployment.probes.readinessProbe.initialDelaySeconds | int | `10` | |
|
||||
| deployment.probes.readinessProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.readinessProbe.successThreshold | int | `1` | |
|
||||
| deployment.probes.readinessProbe.timeoutSeconds | int | `5` | |
|
||||
| deployment.probes.startupProbe.failureThreshold | int | `30` | |
|
||||
| deployment.probes.startupProbe.periodSeconds | int | `10` | |
|
||||
| deployment.probes.startupProbe.tcpSocket.port | int | `3000` | |
|
||||
| deployment.reloadOnChange | bool | `false` | |
|
||||
| deployment.replicas | int | `1` | |
|
||||
| deployment.resources.limits.memory | string | `"2Gi"` | |
|
||||
| deployment.resources.requests.cpu | string | `"1"` | |
|
||||
| deployment.resources.requests.memory | string | `"1Gi"` | |
|
||||
| deployment.revisionHistoryLimit | int | `2` | |
|
||||
| deployment.securityContext | object | `{}` | |
|
||||
| deployment.strategy.type | string | `"RollingUpdate"` | |
|
||||
| deployment.tolerations | list | `[]` | |
|
||||
| deployment.topologySpreadConstraints | list | `[]` | |
|
||||
| enterprise.enabled | bool | `false` | |
|
||||
| enterprise.licenseKey | string | `""` | |
|
||||
| externalSecret.enabled | bool | `false` | |
|
||||
| externalSecret.files | object | `{}` | |
|
||||
| externalSecret.refreshInterval | string | `"1h"` | |
|
||||
| externalSecret.secretStore.kind | string | `"ClusterSecretStore"` | |
|
||||
| externalSecret.secretStore.name | string | `"aws-secrets-manager"` | |
|
||||
| formbricks.publicUrl | string | `""` | |
|
||||
| formbricks.webappUrl | string | `""` | |
|
||||
| hub.enabled | bool | `true` | |
|
||||
| hub.env | object | `{}` | |
|
||||
| hub.existingSecret | string | `""` | |
|
||||
| hub.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| hub.image.repository | string | `"ghcr.io/formbricks/hub"` | |
|
||||
| hub.image.tag | string | `"1.0.0"` | |
|
||||
| hub.migration.activeDeadlineSeconds | int | `900` | |
|
||||
| hub.migration.backoffLimit | int | `3` | |
|
||||
| hub.migration.ttlSecondsAfterFinished | int | `300` | |
|
||||
| hub.replicas | int | `1` | |
|
||||
| hub.resources.limits.memory | string | `"512Mi"` | |
|
||||
| hub.resources.requests.cpu | string | `"100m"` | |
|
||||
| hub.resources.requests.memory | string | `"256Mi"` | |
|
||||
| ingress.annotations | object | `{}` | |
|
||||
| ingress.enabled | bool | `false` | |
|
||||
| ingress.hosts[0].host | string | `"k8s.formbricks.com"` | |
|
||||
| ingress.hosts[0].paths[0].path | string | `"/"` | |
|
||||
| ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | |
|
||||
| ingress.hosts[0].paths[0].serviceName | string | `"formbricks"` | |
|
||||
| ingress.ingressClassName | string | `"alb"` | |
|
||||
| migration.annotations | object | `{}` | |
|
||||
| migration.backoffLimit | int | `3` | |
|
||||
| migration.enabled | bool | `true` | |
|
||||
| migration.resources.limits.memory | string | `"512Mi"` | |
|
||||
| migration.resources.requests.cpu | string | `"100m"` | |
|
||||
| migration.resources.requests.memory | string | `"256Mi"` | |
|
||||
| migration.ttlSecondsAfterFinished | int | `300` | |
|
||||
| nameOverride | string | `""` | |
|
||||
| partOfOverride | string | `""` | |
|
||||
| pdb.additionalLabels | object | `{}` | |
|
||||
| pdb.annotations | object | `{}` | |
|
||||
| pdb.enabled | bool | `true` | |
|
||||
| pdb.minAvailable | int | `1` | |
|
||||
| postgresql.auth.database | string | `"formbricks"` | |
|
||||
| postgresql.auth.existingSecret | string | `"formbricks-app-secrets"` | |
|
||||
| postgresql.auth.secretKeys.adminPasswordKey | string | `"POSTGRES_ADMIN_PASSWORD"` | |
|
||||
| postgresql.auth.secretKeys.userPasswordKey | string | `"POSTGRES_USER_PASSWORD"` | |
|
||||
| postgresql.auth.username | string | `"formbricks"` | |
|
||||
| postgresql.enabled | bool | `true` | |
|
||||
| postgresql.externalDatabaseUrl | string | `""` | |
|
||||
| postgresql.fullnameOverride | string | `"formbricks-postgresql"` | |
|
||||
| postgresql.global.security.allowInsecureImages | bool | `true` | |
|
||||
| postgresql.image.repository | string | `"pgvector/pgvector"` | |
|
||||
| postgresql.image.tag | string | `"pg17"` | |
|
||||
| postgresql.primary.containerSecurityContext.enabled | bool | `true` | |
|
||||
| postgresql.primary.containerSecurityContext.readOnlyRootFilesystem | bool | `false` | |
|
||||
| postgresql.primary.containerSecurityContext.runAsUser | int | `1001` | |
|
||||
| postgresql.primary.networkPolicy.enabled | bool | `false` | |
|
||||
| postgresql.primary.persistence.enabled | bool | `true` | |
|
||||
| postgresql.primary.persistence.size | string | `"10Gi"` | |
|
||||
| postgresql.primary.podSecurityContext.enabled | bool | `true` | |
|
||||
| postgresql.primary.podSecurityContext.fsGroup | int | `1001` | |
|
||||
| postgresql.primary.podSecurityContext.runAsUser | int | `1001` | |
|
||||
| rbac.enabled | bool | `false` | |
|
||||
| rbac.serviceAccount.additionalLabels | object | `{}` | |
|
||||
| rbac.serviceAccount.annotations | object | `{}` | |
|
||||
| rbac.serviceAccount.enabled | bool | `false` | |
|
||||
| rbac.serviceAccount.name | string | `""` | |
|
||||
| redis.architecture | string | `"standalone"` | |
|
||||
| redis.auth.enabled | bool | `true` | |
|
||||
| redis.auth.existingSecret | string | `"formbricks-app-secrets"` | |
|
||||
| redis.auth.existingSecretPasswordKey | string | `"REDIS_PASSWORD"` | |
|
||||
| redis.enabled | bool | `true` | |
|
||||
| redis.externalRedisUrl | string | `""` | |
|
||||
| redis.fullnameOverride | string | `"formbricks-redis"` | |
|
||||
| redis.master.persistence.enabled | bool | `true` | |
|
||||
| redis.networkPolicy.enabled | bool | `false` | |
|
||||
| secret.enabled | bool | `true` | |
|
||||
| service.additionalLabels | object | `{}` | |
|
||||
| service.annotations | object | `{}` | |
|
||||
| service.enabled | bool | `true` | |
|
||||
| service.ports | list | `[]` | |
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
| serviceMonitor.additionalLabels | string | `nil` | |
|
||||
| serviceMonitor.annotations | string | `nil` | |
|
||||
| serviceMonitor.enabled | bool | `true` | |
|
||||
| serviceMonitor.endpoints[0].interval | string | `"5s"` | |
|
||||
| serviceMonitor.endpoints[0].path | string | `"/metrics"` | |
|
||||
| serviceMonitor.endpoints[0].port | string | `"metrics"` | |
|
||||
|
||||
@@ -8,6 +8,15 @@ It also truncates the name to a maximum of 63 characters and removes trailing hy
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Hub resource name: base name truncated to 59 chars then "-hub" so the suffix is never lost (63 char limit).
|
||||
*/}}
|
||||
{{- define "formbricks.hubname" -}}
|
||||
{{- $base := include "formbricks.name" . | trunc 59 | trimSuffix "-" }}
|
||||
{{- printf "%s-hub" $base | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Define the application version to be used in labels.
|
||||
The version is taken from `.Values.deployment.image.tag` if provided, otherwise it defaults to `.Chart.Version`.
|
||||
@@ -85,9 +94,17 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- default .Release.Namespace .Values.namespaceOverride -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "formbricks.appSecretName" -}}
|
||||
{{- printf "%s-app-secrets" (include "formbricks.name" .) -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.hubSecretName" -}}
|
||||
{{- default (include "formbricks.appSecretName" .) .Values.hub.existingSecret -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{- define "formbricks.postgresAdminPassword" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if and $secret (index $secret.data "POSTGRES_ADMIN_PASSWORD") }}
|
||||
{{- index $secret.data "POSTGRES_ADMIN_PASSWORD" | b64dec -}}
|
||||
{{- else }}
|
||||
@@ -96,7 +113,7 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.postgresUserPassword" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if and $secret (index $secret.data "POSTGRES_USER_PASSWORD") }}
|
||||
{{- index $secret.data "POSTGRES_USER_PASSWORD" | b64dec -}}
|
||||
{{- else }}
|
||||
@@ -105,7 +122,7 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.redisPassword" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if and $secret (index $secret.data "REDIS_PASSWORD") }}
|
||||
{{- index $secret.data "REDIS_PASSWORD" | b64dec -}}
|
||||
{{- else }}
|
||||
@@ -114,7 +131,7 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.cronSecret" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if $secret }}
|
||||
{{- index $secret.data "CRON_SECRET" | b64dec -}}
|
||||
{{- else }}
|
||||
@@ -123,7 +140,7 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.encryptionKey" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if $secret }}
|
||||
{{- index $secret.data "ENCRYPTION_KEY" | b64dec -}}
|
||||
{{- else }}
|
||||
@@ -132,10 +149,19 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.nextAuthSecret" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-app-secrets" (include "formbricks.name" .))) }}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if $secret }}
|
||||
{{- index $secret.data "NEXTAUTH_SECRET" | b64dec -}}
|
||||
{{- else }}
|
||||
{{- randAlphaNum 32 -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "formbricks.hubApiKey" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
|
||||
{{- if and $secret (index $secret.data "HUB_API_KEY") }}
|
||||
{{- index $secret.data "HUB_API_KEY" | b64dec -}}
|
||||
{{- else }}
|
||||
{{- randAlphaNum 32 -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
@@ -131,6 +131,10 @@ spec:
|
||||
- name: SKIP_STARTUP_MIGRATION
|
||||
value: "true"
|
||||
{{- end }}
|
||||
{{- if not (hasKey .Values.deployment.env "HUB_API_URL") }}
|
||||
- name: HUB_API_URL
|
||||
value: "http://{{ include "formbricks.hubname" . }}:8080"
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.deployment.env }}
|
||||
- name: {{ include "formbricks.tplvalues.render" ( dict "value" $key "context" $ ) }}
|
||||
{{- if kindIs "string" $value }}
|
||||
|
||||
100
charts/formbricks/templates/hub-deployment.yaml
Normal file
100
charts/formbricks/templates/hub-deployment.yaml
Normal file
@@ -0,0 +1,100 @@
|
||||
{{- if not .Values.hub.enabled }}
|
||||
{{- fail "hub.enabled=false is not supported in Formbricks 5; Hub is mandatory." }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "formbricks.hubname" . }}
|
||||
labels:
|
||||
helm.sh/chart: {{ include "formbricks.chart" . }}
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: hub
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.kubernetes.io/part-of: {{ .Values.partOfOverride | default (include "formbricks.name" .) }}
|
||||
spec:
|
||||
replicas: {{ .Values.hub.replicas | default 1 }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: hub
|
||||
spec:
|
||||
{{- if .Values.deployment.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml .Values.deployment.imagePullSecrets | nindent 8 }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: hub-migrate
|
||||
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
|
||||
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
/usr/local/bin/goose -dir /app/migrations postgres "$DATABASE_URL" up && \
|
||||
/usr/local/bin/river migrate-up --database-url "$DATABASE_URL"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "formbricks.hubSecretName" . }}
|
||||
containers:
|
||||
- name: hub
|
||||
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
|
||||
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "formbricks.hubSecretName" . }}
|
||||
env:
|
||||
- name: API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "formbricks.hubSecretName" . }}
|
||||
key: HUB_API_KEY
|
||||
{{- range $key, $value := .Values.hub.env }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.hub.resources }}
|
||||
resources:
|
||||
{{- toYaml .Values.hub.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
failureThreshold: 5
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
failureThreshold: 5
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
failureThreshold: 30
|
||||
periodSeconds: 10
|
||||
54
charts/formbricks/templates/hub-migration-job.yaml
Normal file
54
charts/formbricks/templates/hub-migration-job.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
{{- if not .Values.hub.enabled }}
|
||||
{{- fail "hub.enabled=false is not supported in Formbricks 5; Hub is mandatory." }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ include "formbricks.hubname" . }}-migration
|
||||
labels:
|
||||
helm.sh/chart: {{ include "formbricks.chart" . }}
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: hub-migration
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
annotations:
|
||||
helm.sh/hook: pre-upgrade
|
||||
helm.sh/hook-weight: "-5"
|
||||
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
|
||||
spec:
|
||||
ttlSecondsAfterFinished: {{ .Values.hub.migration.ttlSecondsAfterFinished | default 300 }}
|
||||
backoffLimit: {{ .Values.hub.migration.backoffLimit | default 3 }}
|
||||
activeDeadlineSeconds: {{ .Values.hub.migration.activeDeadlineSeconds | default 900 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: hub-migration
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
{{- if .Values.deployment.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml .Values.deployment.imagePullSecrets | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: hub-migrate
|
||||
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
|
||||
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
/usr/local/bin/goose -dir /app/migrations postgres "$DATABASE_URL" up && \
|
||||
/usr/local/bin/river migrate-up --database-url "$DATABASE_URL"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "formbricks.hubSecretName" . }}
|
||||
25
charts/formbricks/templates/hub-service.yaml
Normal file
25
charts/formbricks/templates/hub-service.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
{{- if not .Values.hub.enabled }}
|
||||
{{- fail "hub.enabled=false is not supported in Formbricks 5; Hub is mandatory." }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "formbricks.hubname" . }}
|
||||
labels:
|
||||
helm.sh/chart: {{ include "formbricks.chart" . }}
|
||||
app.kubernetes.io/name: {{ include "formbricks.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/component: hub
|
||||
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.hubname" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
@@ -4,11 +4,13 @@
|
||||
{{- $postgresUserPassword := include "formbricks.postgresUserPassword" . }}
|
||||
{{- $redisPassword := include "formbricks.redisPassword" . }}
|
||||
{{- $webappUrl := required "formbricks.webappUrl is required. Set it to your Formbricks instance URL (e.g., https://formbricks.example.com)" .Values.formbricks.webappUrl }}
|
||||
{{- $hubApiKey := include "formbricks.hubApiKey" . }}
|
||||
{{- $includeHubApiKeyInAppSecret := or (not .Values.hub.existingSecret) (eq .Values.hub.existingSecret (include "formbricks.appSecretName" .)) }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "formbricks.name" . }}-app-secrets
|
||||
name: {{ include "formbricks.appSecretName" . }}
|
||||
labels:
|
||||
{{- include "formbricks.labels" . | nindent 4 }}
|
||||
data:
|
||||
@@ -28,6 +30,9 @@ data:
|
||||
{{- else }}
|
||||
DATABASE_URL: {{ .Values.postgresql.externalDatabaseUrl | b64enc }}
|
||||
{{- end }}
|
||||
{{- if $includeHubApiKeyInAppSecret }}
|
||||
HUB_API_KEY: {{ $hubApiKey | b64enc }}
|
||||
{{- end }}
|
||||
CRON_SECRET: {{ include "formbricks.cronSecret" . | b64enc }}
|
||||
ENCRYPTION_KEY: {{ include "formbricks.encryptionKey" . | b64enc }}
|
||||
NEXTAUTH_SECRET: {{ include "formbricks.nextAuthSecret" . | b64enc }}
|
||||
|
||||
@@ -340,6 +340,43 @@ serviceMonitor:
|
||||
path: /metrics
|
||||
port: metrics
|
||||
|
||||
##########################################################
|
||||
# Hub API Configuration
|
||||
# Formbricks Hub image: ghcr.io/formbricks/hub
|
||||
##########################################################
|
||||
hub:
|
||||
# Hub is mandatory in Formbricks 5. Keep this enabled.
|
||||
enabled: true
|
||||
replicas: 1
|
||||
|
||||
image:
|
||||
repository: "ghcr.io/formbricks/hub"
|
||||
# Pin to a semver tag for reproducible deployments; update on each Hub release.
|
||||
tag: "1.0.0"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Optional override for the secret Hub reads from.
|
||||
# Defaults to the generated app secret (<release>-app-secrets), which contains DATABASE_URL and HUB_API_KEY.
|
||||
# If you set this, the custom secret must provide DATABASE_URL and HUB_API_KEY.
|
||||
existingSecret: ""
|
||||
|
||||
# Optional env vars (non-secret). Use existingSecret for secret values such as DATABASE_URL and HUB_API_KEY.
|
||||
env: {}
|
||||
|
||||
# Upgrade migration job runs goose + river before Helm upgrades Hub resources.
|
||||
# Fresh installs run the same migrations through the Hub deployment init container.
|
||||
migration:
|
||||
ttlSecondsAfterFinished: 300
|
||||
backoffLimit: 3
|
||||
activeDeadlineSeconds: 900
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: "100m"
|
||||
|
||||
##########################################################
|
||||
# PostgreSQL Configuration
|
||||
##########################################################
|
||||
@@ -352,7 +389,7 @@ postgresql:
|
||||
fullnameOverride: "formbricks-postgresql"
|
||||
image:
|
||||
repository: pgvector/pgvector
|
||||
tag: 0.8.0-pg17
|
||||
tag: pg17
|
||||
auth:
|
||||
username: formbricks
|
||||
database: formbricks
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
services:
|
||||
# PostgreSQL must load the vector library so Hub (and Formbricks) can use the pgvector extension.
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg17
|
||||
image: pgvector/pgvector:pg18
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql/data
|
||||
- postgres:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=postgres
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
command: >
|
||||
postgres
|
||||
-c shared_preload_libraries=vector
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
start_period: 10s
|
||||
|
||||
mailhog:
|
||||
image: arjenz/mailhog
|
||||
@@ -36,6 +46,40 @@ services:
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
|
||||
# Run Hub DB migrations (goose + river) before the API starts. Idempotent; runs on every compose up.
|
||||
hub-migrate:
|
||||
image: ghcr.io/formbricks/hub:latest
|
||||
restart: "no"
|
||||
entrypoint: ["sh", "-c"]
|
||||
command:
|
||||
[
|
||||
'if [ -x /usr/local/bin/goose ] && [ -x /usr/local/bin/river ]; then /usr/local/bin/goose -dir /app/migrations postgres "$$DATABASE_URL" up && /usr/local/bin/river migrate-up --database-url "$$DATABASE_URL"; else echo ''Migration tools (goose/river) not in image.''; exit 1; fi',
|
||||
]
|
||||
environment:
|
||||
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
# Formbricks Hub API (ghcr.io/formbricks/hub). Shares the same Postgres database as Formbricks by default.
|
||||
hub:
|
||||
image: ghcr.io/formbricks/hub:latest
|
||||
depends_on:
|
||||
hub-migrate:
|
||||
condition: service_completed_successfully
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
API_KEY: ${HUB_API_KEY:-dev-api-key}
|
||||
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable
|
||||
# Explicit Postgres env so migrations and any libpq fallback use the service host, not localhost
|
||||
PGHOST: postgres
|
||||
PGPORT: "5432"
|
||||
PGUSER: postgres
|
||||
PGPASSWORD: postgres
|
||||
PGDATABASE: postgres
|
||||
PGSSLMODE: disable
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
driver: local
|
||||
|
||||
@@ -27,3 +27,13 @@ The script will prompt you for the following information:
|
||||
3. **Domain Name**: Enter the domain name that Traefik will use to create the SSL certificate and forward requests to Formbricks.
|
||||
|
||||
That's it! After running the command and providing the required information, visit the domain name you entered, and you should see the Formbricks home wizard!
|
||||
|
||||
## Formbricks Hub
|
||||
|
||||
The stack includes the [Formbricks Hub](https://github.com/formbricks/hub) API (`ghcr.io/formbricks/hub`). Hub shares the same database as Formbricks by default.
|
||||
|
||||
- **Migrations**: A `hub-migrate` service runs Hub's database migrations (goose + river) before the Hub API starts. It runs on every `docker compose up` and is idempotent.
|
||||
- **Production** (`docker/docker-compose.yml`): Set `HUB_API_KEY` (required). `HUB_API_URL` defaults to `http://hub:8080` so the Formbricks app can reach Hub inside the compose network. Override `HUB_DATABASE_URL` only if you want Hub to use a separate database.
|
||||
- **Development** (`docker-compose.dev.yml`): Hub uses the same Postgres database; `HUB_API_KEY` defaults to `dev-api-key` (override with `HUB_API_KEY`) and the local Hub URL is `http://localhost:8080`.
|
||||
|
||||
In development, Hub is exposed locally on port **8080**. In production Docker Compose, Hub stays internal to the compose network and is reached via `http://hub:8080`.
|
||||
|
||||
@@ -29,6 +29,15 @@ x-environment: &environment
|
||||
# To use external Redis/Valkey: remove the redis service below and update this URL
|
||||
REDIS_URL: redis://redis:6379
|
||||
|
||||
# Formbricks Hub (port 8080): API key required. Use e.g. openssl rand -hex 32
|
||||
HUB_API_KEY:
|
||||
|
||||
# Base URL the Formbricks app uses to reach Hub. Defaults to the internal Hub service.
|
||||
HUB_API_URL: ${HUB_API_URL:-http://hub:8080}
|
||||
|
||||
# Hub database URL (optional). Default: same Postgres as Formbricks. Set only if Hub uses a separate DB.
|
||||
# HUB_DATABASE_URL:
|
||||
|
||||
# Set the minimum log level(debug, info, warn, error, fatal)
|
||||
# LOG_LEVEL: info
|
||||
|
||||
@@ -202,7 +211,7 @@ x-environment: &environment
|
||||
services:
|
||||
postgres:
|
||||
restart: always
|
||||
image: pgvector/pgvector:pg17
|
||||
image: pgvector/pgvector:pg18
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql/data
|
||||
environment:
|
||||
@@ -245,6 +254,31 @@ services:
|
||||
- ./saml-connection:/home/nextjs/apps/web/saml-connection
|
||||
<<: *environment
|
||||
|
||||
# Run Hub DB migrations (goose + river) before the API starts. Uses same image; migrations are idempotent.
|
||||
hub-migrate:
|
||||
image: ghcr.io/formbricks/hub:latest
|
||||
restart: "no"
|
||||
entrypoint: ["sh", "-c"]
|
||||
command: ["if [ -x /usr/local/bin/goose ] && [ -x /usr/local/bin/river ]; then /usr/local/bin/goose -dir /app/migrations postgres \"$$DATABASE_URL\" up && /usr/local/bin/river migrate-up --database-url \"$$DATABASE_URL\"; else echo 'Migration tools (goose/river) not in image.'; exit 1; fi"]
|
||||
environment:
|
||||
DATABASE_URL: ${HUB_DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/formbricks?sslmode=disable}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
# Formbricks Hub API (ghcr.io/formbricks/hub). Set HUB_API_KEY. By default shares the Formbricks database; set HUB_DATABASE_URL to use a separate DB.
|
||||
hub:
|
||||
restart: always
|
||||
image: ghcr.io/formbricks/hub:latest
|
||||
depends_on:
|
||||
hub-migrate:
|
||||
condition: service_completed_successfully
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
API_KEY: ${HUB_API_KEY:?HUB_API_KEY is required to run Hub}
|
||||
DATABASE_URL: ${HUB_DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/formbricks?sslmode=disable}
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
driver: local
|
||||
|
||||
@@ -77,4 +77,14 @@ These variables are present inside your machine's docker-compose file. Restart t
|
||||
| AUDIT_LOG_ENABLED | Set this to 1 to enable audit logging. Requires Redis to be configured with the REDIS_URL env variable. | optional | 0 |
|
||||
| AUDIT_LOG_GET_USER_IP | Set to 1 to include user IP addresses in audit logs from request headers | optional | 0 |
|
||||
|
||||
#### Formbricks Hub
|
||||
|
||||
When running the stack with [Formbricks Hub](https://github.com/formbricks/hub) (for example via Docker Compose or Helm), the following variables apply:
|
||||
|
||||
| Variable | Description | Required | Default |
|
||||
| ---------------- | ------------------------------------------------------------------------------------------------ | -------------------------- | ----------------------------------------------------- |
|
||||
| HUB_API_KEY | API key used by the Formbricks Hub API (port 8080). | required | (e.g. `openssl rand -hex 32`) |
|
||||
| HUB_API_URL | Base URL the Formbricks app uses to call Hub. Use `http://localhost:8080` locally. | required | `http://localhost:8080` in local dev |
|
||||
| HUB_DATABASE_URL | PostgreSQL connection URL for Hub. Omit to use the same database as Formbricks. | optional | Same as Formbricks `DATABASE_URL` (shared database) |
|
||||
|
||||
Note: If you want to configure something that is not possible via above, please open an issue on our GitHub repo here or reach out to us on Github Discussions and we'll try our best to work out a solution with you.
|
||||
|
||||
@@ -156,6 +156,8 @@
|
||||
"GOOGLE_SHEETS_CLIENT_ID",
|
||||
"GOOGLE_SHEETS_CLIENT_SECRET",
|
||||
"GOOGLE_SHEETS_REDIRECT_URL",
|
||||
"HUB_API_KEY",
|
||||
"HUB_API_URL",
|
||||
"NOTION_OAUTH_CLIENT_ID",
|
||||
"NOTION_OAUTH_CLIENT_SECRET",
|
||||
"HEROKU_APP_NAME",
|
||||
|
||||
Reference in New Issue
Block a user