Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ DATABASE_URL='postgresql://postgres:postgres@localhost:5432/formbricks?schema=pu
HUB_API_KEY=dev-api-key
HUB_API_URL=http://localhost:8080
HUB_DATABASE_URL=postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable
# Hub image tag used by docker-compose.dev.yml (hub + hub-migrate). Leave unset to use the
# pinned default in the compose file; override here when testing a specific Hub release.
# HUB_IMAGE_TAG=0.2.0

###########################
# CUBE ANALYTICS (XM V5) #
Expand Down
3 changes: 2 additions & 1 deletion charts/formbricks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ This chart does not deploy Cube.js. XM Suite v5 dashboard and analysis features
| hub.enabled | bool | `true` | |
| hub.env | object | `{}` | |
| hub.existingSecret | string | `""` | |
| hub.image.digest | string | `"sha256:14db7b3d285b6e9165b55693f9b83d08beff840a255fd77dd12882ee0a62f5cb"` | When set, takes precedence over tag (immutable pin). |
| hub.image.pullPolicy | string | `"IfNotPresent"` | |
| hub.image.repository | string | `"ghcr.io/formbricks/hub"` | |
| hub.image.tag | string | `"1.0.0"` | |
| hub.image.tag | string | `"0.2.0"` | Fallback when digest is empty. |
| hub.migration.activeDeadlineSeconds | int | `900` | |
| hub.migration.backoffLimit | int | `3` | |
| hub.migration.ttlSecondsAfterFinished | int | `300` | |
Expand Down
13 changes: 13 additions & 0 deletions charts/formbricks/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ If `namespaceOverride` is provided, it will be used; otherwise, it defaults to `
{{- default (include "formbricks.appSecretName" .) .Values.hub.existingSecret -}}
{{- end }}

{{/*
Hub image reference. Pin by digest in production (hub.image.digest = "sha256:..."); falls back to
hub.image.tag for local/dev. All Hub workloads (deployment, init container, migration job, future
hub-worker) must use this helper so they cannot drift apart.
*/}}
{{- define "formbricks.hubImage" -}}
{{- if .Values.hub.image.digest -}}
{{- printf "%s@%s" .Values.hub.image.repository .Values.hub.image.digest -}}
{{- else -}}
{{- printf "%s:%s" .Values.hub.image.repository (.Values.hub.image.tag | default "latest") -}}
{{- end -}}
{{- end }}
Comment thread
pandeymangg marked this conversation as resolved.


{{- define "formbricks.postgresAdminPassword" -}}
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "formbricks.appSecretName" .)) }}
Expand Down
4 changes: 2 additions & 2 deletions charts/formbricks/templates/hub-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ spec:
{{- end }}
initContainers:
- name: hub-migrate
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
image: {{ include "formbricks.hubImage" . }}
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
securityContext:
readOnlyRootFilesystem: true
Expand All @@ -48,7 +48,7 @@ spec:
name: {{ include "formbricks.hubSecretName" . }}
containers:
- name: hub
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
image: {{ include "formbricks.hubImage" . }}
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
securityContext:
readOnlyRootFilesystem: true
Expand Down
2 changes: 1 addition & 1 deletion charts/formbricks/templates/hub-migration-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ spec:
{{- end }}
containers:
- name: hub-migrate
image: {{ .Values.hub.image.repository }}:{{ .Values.hub.image.tag | default "latest" }}
image: {{ include "formbricks.hubImage" . }}
imagePullPolicy: {{ .Values.hub.image.pullPolicy }}
securityContext:
readOnlyRootFilesystem: true
Expand Down
9 changes: 7 additions & 2 deletions charts/formbricks/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,13 @@ hub:

image:
repository: "ghcr.io/formbricks/hub"
# Pin to a semver tag for reproducible deployments; update on each Hub release.
tag: "1.0.0"
# Pinned by digest for immutable, reproducible deployments. When digest is set it takes
# precedence over tag, and deployment, init container, and migration job all resolve to the
# same immutable image. Update on each Hub release.
# Current digest corresponds to ghcr.io/formbricks/hub:0.2.0.
digest: "sha256:14db7b3d285b6e9165b55693f9b83d08beff840a255fd77dd12882ee0a62f5cb"
# Tag is a fallback for dev/non-prod when digest is cleared; keep aligned with the digest above.
tag: "0.2.0"
pullPolicy: IfNotPresent

# Optional override for the secret Hub reads from.
Expand Down
7 changes: 5 additions & 2 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ services:
- minio-data:/data

# Run Hub DB migrations (goose + river) before the API starts. Idempotent; runs on every compose up.
# Hub image pinned via HUB_IMAGE_TAG so docker does not silently reuse a stale :latest cache.
# Keep hub, hub-migrate, and any future hub-worker on the same tag — they share one image and
# drift breaks migrations or job processing.
hub-migrate:
image: ghcr.io/formbricks/hub:latest
image: ghcr.io/formbricks/hub:${HUB_IMAGE_TAG:-0.2.0}
restart: "no"
entrypoint: ["sh", "-c"]
command:
Expand All @@ -63,7 +66,7 @@ services:

# Formbricks Hub API (ghcr.io/formbricks/hub). Shares the same Postgres database as Formbricks by default.
hub:
image: ghcr.io/formbricks/hub:latest
image: ghcr.io/formbricks/hub:${HUB_IMAGE_TAG:-0.2.0}
depends_on:
hub-migrate:
condition: service_completed_successfully
Expand Down
4 changes: 2 additions & 2 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ That's it! After running the command and providing the required information, vis
The stack includes the [Formbricks Hub](https://github.com/formbricks/hub) API (`ghcr.io/formbricks/hub`) and a bundled Cube.js service for XM Suite v5 analytics. Hub and Cube share 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` and `CUBEJS_API_SECRET` (required). `HUB_API_URL` defaults to `http://hub:8080` and `CUBEJS_API_URL` defaults to `http://cube:4000` so the Formbricks app can reach both services inside the compose network. Override `HUB_DATABASE_URL` and `CUBEJS_DB_*` only if Hub or Cube should use a separate database.
- **Development** (`docker-compose.dev.yml`): Hub and Cube use the same local Postgres database. `HUB_API_KEY` defaults to `dev-api-key`, `CUBEJS_API_URL` defaults to `http://localhost:4000`, and `pnpm dev:setup` generates `CUBEJS_API_SECRET` in the repo root `.env`.
- **Production** (`docker/docker-compose.yml`): Set `HUB_API_KEY` and `CUBEJS_API_SECRET` (required). `HUB_API_URL` defaults to `http://hub:8080` and `CUBEJS_API_URL` defaults to `http://cube:4000` so the Formbricks app can reach both services inside the compose network. Override `HUB_DATABASE_URL` and `CUBEJS_DB_*` only if Hub or Cube should use a separate database. The Hub image tracks `:latest` by default so `formbricks.sh update` advances Hub in lockstep with the app. `hub` and `hub-migrate` always resolve to the same image. To pin to an immutable reference, set `HUB_IMAGE_REF` in `docker/.env` to either a tag (e.g. `:0.2.0`) or a digest (e.g. `@sha256:14db7b3d…`).
- **Development** (`docker-compose.dev.yml`): Hub and Cube use the same local Postgres database. `HUB_API_KEY` defaults to `dev-api-key`, `CUBEJS_API_URL` defaults to `http://localhost:4000`, and `pnpm dev:setup` generates `CUBEJS_API_SECRET` in the repo root `.env`. The Hub image is pinned to a semver tag (`hub` and `hub-migrate` share the same value); override `HUB_IMAGE_TAG` in the repo root `.env` to test a specific Hub release.

In development, Hub is exposed locally on port **8080** and Cube on **4000** (with the Cube playground on **4001**). In production Docker Compose, Hub and Cube stay internal to the compose network and are reached via `http://hub:8080` and `http://cube:4000`.
7 changes: 5 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,11 @@ services:
<<: *environment

# Run Hub DB migrations (goose + river) before the API starts. Uses same image; migrations are idempotent.
# Default tracks :latest so self-host updates (compose pull) advance Hub alongside the app image.
# Operators who want an immutable pin can set HUB_IMAGE_REF in docker/.env to either ":<tag>"
# (e.g. ":0.2.0") or "@sha256:<digest>". hub and hub-migrate share the same value — no drift.
hub-migrate:
image: ghcr.io/formbricks/hub:latest
image: ghcr.io/formbricks/hub${HUB_IMAGE_REF:-:latest}
restart: "no"
entrypoint: ["sh", "-c"]
command:
Expand All @@ -279,7 +282,7 @@ services:
# 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
image: ghcr.io/formbricks/hub${HUB_IMAGE_REF:-:latest}
depends_on:
hub-migrate:
condition: service_completed_successfully
Expand Down
Loading