Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/formbricks/formbricks/llms.txt

Use this file to discover all available pages before exploring further.

Deploy Formbricks on Kubernetes for enterprise-grade, scalable infrastructure with auto-scaling, high availability, and easy management.

Prerequisites

  • A Kubernetes cluster (1.27+)
  • kubectl configured to access your cluster
  • helm CLI installed (v3.0+)
  • Ingress controller (e.g., NGINX, Traefik, or AWS ALB)
  • Storage class for persistent volumes

Quick Start

1

Add Formbricks Helm Repository

helm repo add formbricks https://formbricks.github.io/helm-charts
helm repo update
The Helm charts are maintained in the Formbricks repository at /charts/formbricks.
2

Create a Values File

Create a values.yaml file with your configuration:
values.yaml
formbricks:
  # REQUIRED: Your Formbricks domain
  webappUrl: "https://formbricks.example.com"

# Enable ingress for external access
ingress:
  enabled: true
  ingressClassName: nginx  # or 'alb', 'traefik', etc.
  hosts:
    - host: formbricks.example.com
      paths:
        - path: /
          pathType: Prefix
          serviceName: formbricks
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod

# PostgreSQL with pgvector
postgresql:
  enabled: true
  auth:
    username: formbricks
    database: formbricks
  primary:
    persistence:
      enabled: true
      size: 20Gi

# Redis for caching
redis:
  enabled: true
  architecture: standalone
  master:
    persistence:
      enabled: true
      size: 5Gi

# Auto-scaling configuration
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

# Resource allocation
deployment:
  resources:
    requests:
      memory: "1Gi"
      cpu: "1"
    limits:
      memory: "2Gi"
3

Create Secrets

Generate required secrets:
# Generate secrets
NEXTAUTH_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
CRON_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 32)
REDIS_PASSWORD=$(openssl rand -hex 32)

# Create Kubernetes secret
kubectl create secret generic formbricks-app-secrets \
  --from-literal=NEXTAUTH_SECRET=$NEXTAUTH_SECRET \
  --from-literal=ENCRYPTION_KEY=$ENCRYPTION_KEY \
  --from-literal=CRON_SECRET=$CRON_SECRET \
  --from-literal=POSTGRES_USER_PASSWORD=$POSTGRES_PASSWORD \
  --from-literal=POSTGRES_ADMIN_PASSWORD=$POSTGRES_PASSWORD \
  --from-literal=REDIS_PASSWORD=$REDIS_PASSWORD
Store these secrets securely. You’ll need them for disaster recovery.
4

Install the Helm Chart

Deploy Formbricks to your cluster:
helm install formbricks formbricks/formbricks \
  -f values.yaml \
  --namespace formbricks \
  --create-namespace
5

Verify Deployment

Check that all pods are running:
kubectl get pods -n formbricks
Expected output:
NAME                                    READY   STATUS    RESTARTS   AGE
formbricks-6d5f8c7b4d-abc12            1/1     Running   0          2m
formbricks-6d5f8c7b4d-def34            1/1     Running   0          2m
formbricks-postgresql-0                1/1     Running   0          2m
formbricks-redis-master-0              1/1     Running   0          2m
6

Access Your Instance

Get the ingress address:
kubectl get ingress -n formbricks
Navigate to your configured domain to complete the setup wizard.

Architecture Overview

The Helm chart deploys the following components:

Configuration Reference

Core Configuration

ParameterDescriptionDefault
formbricks.webappUrlPublic URL of your instance (required)""
formbricks.publicUrlAlternative public URL for surveysSame as webappUrl
deployment.replicasInitial number of replicas1
deployment.image.repositoryContainer imageghcr.io/formbricks/formbricks
deployment.image.tagImage tagChart appVersion

Database Configuration

Use the bundled PostgreSQL with pgvector:
postgresql:
  enabled: true
  image:
    repository: pgvector/pgvector
    tag: 0.8.0-pg17
  auth:
    username: formbricks
    database: formbricks
    existingSecret: formbricks-app-secrets
    secretKeys:
      adminPasswordKey: POSTGRES_ADMIN_PASSWORD
      userPasswordKey: POSTGRES_USER_PASSWORD
  primary:
    persistence:
      enabled: true
      size: 20Gi
      storageClass: ""  # Use default storage class
Connect to an external PostgreSQL instance:
postgresql:
  enabled: false
  externalDatabaseUrl: "postgresql://user:pass@host:5432/formbricks?schema=public"
Add the connection string to your secrets:
kubectl create secret generic formbricks-app-secrets \
  --from-literal=DATABASE_URL="postgresql://user:pass@host:5432/formbricks?schema=public" \
  # ... other secrets

Redis Configuration

Use the bundled Redis/Valkey:
redis:
  enabled: true
  architecture: standalone
  auth:
    enabled: true
    existingSecret: formbricks-app-secrets
    existingSecretPasswordKey: REDIS_PASSWORD
  master:
    persistence:
      enabled: true
      size: 5Gi
Connect to an external Redis instance:
redis:
  enabled: false
  externalRedisUrl: "redis://:password@host:6379"

Auto-Scaling Configuration

The Horizontal Pod Autoscaler (HPA) automatically scales pods based on resource usage:
autoscaling:
  enabled: true
  minReplicas: 2  # Minimum for high availability
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60  # Scale up at 60% CPU
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 60  # Scale up at 60% memory
  
  # Scale-down behavior (prevents flapping)
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # Wait 5 minutes
      policies:
        - type: Pods
          value: 1
          periodSeconds: 120  # Remove 1 pod every 2 minutes
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 2
          periodSeconds: 60  # Add 2 pods every minute

Pod Disruption Budget

Ensure availability during cluster maintenance:
pdb:
  enabled: true
  minAvailable: 1  # Always keep at least 1 pod running
  # OR use maxUnavailable:
  # maxUnavailable: 1
With minAvailable: 1 and only 1 replica, the PDB will block node drains. Always run at least 2 replicas in production.

Ingress Configuration

ingress:
  enabled: true
  ingressClassName: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
  hosts:
    - host: formbricks.example.com
      paths:
        - path: /
          pathType: Prefix
          serviceName: formbricks
  tls:
    - secretName: formbricks-tls
      hosts:
        - formbricks.example.com

Advanced Configuration

External Secrets Operator

Use External Secrets Operator for AWS Secrets Manager, Azure Key Vault, or Google Secret Manager:
externalSecret:
  enabled: true
  secretStore:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  refreshInterval: "1h"
  files:
    NEXTAUTH_SECRET:
      key: formbricks/production
      property: nextauth_secret
    ENCRYPTION_KEY:
      key: formbricks/production
      property: encryption_key

SMTP Configuration

Enable email features by adding SMTP credentials to your secrets:
kubectl create secret generic formbricks-app-secrets \
  --from-literal=MAIL_FROM="noreply@example.com" \
  --from-literal=SMTP_HOST="smtp.gmail.com" \
  --from-literal=SMTP_PORT="587" \
  --from-literal=SMTP_USER="your-email@gmail.com" \
  --from-literal=SMTP_PASSWORD="your-app-password" \
  # ... other secrets
Update your values:
deployment:
  env:
    EMAIL_VERIFICATION_DISABLED:
      value: "0"
    PASSWORD_RESET_DISABLED:
      value: "0"
    SMTP_SECURE_ENABLED:
      value: "1"

S3 File Storage

Configure S3 for file uploads:
kubectl create secret generic formbricks-app-secrets \
  --from-literal=S3_ACCESS_KEY="your-access-key" \
  --from-literal=S3_SECRET_KEY="your-secret-key" \
  --from-literal=S3_REGION="us-east-1" \
  --from-literal=S3_BUCKET_NAME="formbricks-uploads" \
  # ... other secrets

Enterprise Features

Enable Enterprise features with a license key:
enterprise:
  enabled: true
  licenseKey: "your-enterprise-license-key"

Monitoring with Prometheus

The chart includes a ServiceMonitor for Prometheus Operator:
serviceMonitor:
  enabled: true
  additionalLabels:
    prometheus: kube-prometheus
  endpoints:
    - interval: 30s
      path: /metrics
      port: metrics

Maintenance Operations

Upgrading Formbricks

1

Update Helm Repository

helm repo update formbricks
2

Check for Changes

helm diff upgrade formbricks formbricks/formbricks \
  -f values.yaml \
  -n formbricks
3

Upgrade Release

helm upgrade formbricks formbricks/formbricks \
  -f values.yaml \
  -n formbricks
Database migrations run automatically via a pre-sync hook.
4

Monitor Rollout

kubectl rollout status deployment/formbricks -n formbricks

Backup and Restore

Backup PostgreSQL

# Create a backup
kubectl exec -n formbricks formbricks-postgresql-0 -- \
  pg_dump -U formbricks formbricks > formbricks-backup.sql

Restore PostgreSQL

# Restore from backup
kubectl exec -i -n formbricks formbricks-postgresql-0 -- \
  psql -U formbricks formbricks < formbricks-backup.sql

Automated Backups with Velero

# Install Velero
velero install --provider aws --bucket formbricks-backups \
  --secret-file ./credentials-velero

# Create backup schedule
velero schedule create formbricks-daily \
  --schedule="0 2 * * *" \
  --include-namespaces formbricks

Scaling

Manual Scaling

# Scale to specific replica count
kubectl scale deployment formbricks -n formbricks --replicas=5

Adjust HPA Limits

# Update HPA
kubectl patch hpa formbricks -n formbricks \
  --patch '{"spec":{"maxReplicas":20}}'

Troubleshooting

Check pod status and logs:
kubectl describe pod -n formbricks -l app.kubernetes.io/name=formbricks
kubectl logs -n formbricks -l app.kubernetes.io/name=formbricks --tail=100
Common issues:
  • Missing secrets
  • Database connection failures
  • Insufficient resources
Check the migration job logs:
kubectl logs -n formbricks -l job-name=formbricks-migration
Manually run migrations if needed:
kubectl exec -it -n formbricks deployment/formbricks -- \
  pnpm --filter=web db:migrate:deploy
Verify ingress configuration:
kubectl describe ingress -n formbricks
kubectl get svc -n formbricks
Check ingress controller logs:
# For NGINX
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
Adjust resource limits:
deployment:
  resources:
    limits:
      memory: "4Gi"
    requests:
      memory: "2Gi"
Enable vertical pod autoscaling:
kubectl apply -f - <<EOF
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: formbricks-vpa
  namespace: formbricks
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: formbricks
  updatePolicy:
    updateMode: "Auto"
EOF

Security Best Practices

Network Policies

Restrict pod-to-pod communication:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: formbricks-network-policy
  namespace: formbricks
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: formbricks
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
  egress:
    - to:
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: postgresql
    - to:
        - podSelector:
            matchLabels:
              app.kubernetes.io/name: redis

Pod Security Standards

The chart follows Pod Security Standards (restricted):
deployment:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
  containerSecurityContext:
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop:
        - ALL

Next Steps

Production Checklist

Ensure your deployment is production-ready

Monitoring Setup

Set up observability and alerts