Self-Hosting Formbricks with Docker Compose
Why Self-Host Your Forms?
Google Forms sends your respondent data to Google. Typeform charges $29+/month for basic logic branching. Formbricks gives you both — a polished form builder with conditional logic, analytics, and multi-language support — entirely on your own infrastructure.
Formbricks is an open-source experience management platform. It handles surveys, product feedback forms, website popups, and in-app micro-surveys. The form builder is drag-and-drop with question types, logic jumps, and response piping. Results come with built-in analytics — no external tools needed.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 2 GB RAM minimum
- 15 GB free disk space
- A domain name (required for production)
- SMTP access for email notifications (optional but recommended)
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 2 GB (total stack) | 4 GB |
| CPU | 1 core | 2 cores |
| Disk | 15 GB | 30 GB |
Formbricks runs on Next.js with PostgreSQL (pgvector) and Redis. The stack is heavier than a static form tool but lighter than most survey platforms.
Docker Compose Configuration
Create a docker-compose.yml:
services:
formbricks:
image: ghcr.io/formbricks/formbricks:v4.7.5
container_name: formbricks
depends_on:
formbricks-db:
condition: service_healthy
formbricks-redis:
condition: service_started
environment:
- WEBAPP_URL=${WEBAPP_URL}
- NEXTAUTH_URL=${WEBAPP_URL}
- DATABASE_URL=postgres://formbricks:${DB_PASSWORD}@formbricks-db:5432/formbricks
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- CRON_SECRET=${CRON_SECRET}
# Email (optional but needed for invitations and password resets)
- MAIL_FROM=${MAIL_FROM:[email protected]}
- SMTP_HOST=${SMTP_HOST:-}
- SMTP_PORT=${SMTP_PORT:-587}
- SMTP_USER=${SMTP_USER:-}
- SMTP_PASSWORD=${SMTP_PASSWORD:-}
- SMTP_SECURE_ENABLED=${SMTP_SECURE:-1}
ports:
- "3000:3000"
restart: unless-stopped
formbricks-db:
image: pgvector/pgvector:pg17
container_name: formbricks-db
environment:
- POSTGRES_DB=formbricks
- POSTGRES_USER=formbricks
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- formbricks_db:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U formbricks"]
interval: 10s
timeout: 5s
retries: 5
formbricks-redis:
image: valkey/valkey:8-alpine
container_name: formbricks-redis
volumes:
- formbricks_redis:/data
restart: unless-stopped
volumes:
formbricks_db:
formbricks_redis:
Create a .env file:
# Your public URL — MUST match exactly (no trailing slash)
WEBAPP_URL=https://forms.example.com
# Database password — change this
DB_PASSWORD=change_me_strong_password
# Generate all three secrets:
# openssl rand -hex 32
NEXTAUTH_SECRET=generate_me
ENCRYPTION_KEY=generate_me
CRON_SECRET=generate_me
# Email (optional — needed for invitations)
MAIL_FROM=[email protected]
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD=your_smtp_password
SMTP_SECURE=1
Generate the secrets:
for var in NEXTAUTH_SECRET ENCRYPTION_KEY CRON_SECRET; do
echo "${var}=$(openssl rand -hex 32)" >> .env
done
Start the stack:
docker compose up -d
Initial Setup
- Open
https://forms.example.comin your browser - Create your account — the first user becomes the organization admin
- Complete the onboarding: organization name, role, and use case
- You’re dropped into the dashboard — click Create Survey to build your first form
Question Types Available
| Type | Description |
|---|---|
| Single Select | Radio buttons / dropdown |
| Multi Select | Checkboxes |
| Open Text | Short or long text input |
| Rating | Star rating or emoji scale |
| NPS | Net Promoter Score (0-10) |
| CTA | Call-to-action button |
| Consent | GDPR/privacy consent checkbox |
| Date | Date picker |
| File Upload | Drag-and-drop file attachment |
| Address | Structured address fields |
| Matrix | Grid/table questions |
| Picture Selection | Image-based choices |
All question types support conditional logic — show or hide questions based on previous answers.
Distribution Methods
Formbricks supports multiple ways to reach respondents:
| Method | How It Works | Best For |
|---|---|---|
| Link surveys | Shareable URL, standalone form page | External surveys, feedback collection |
| Website surveys | JavaScript widget, in-page popup | On-site feedback, exit intent |
| App surveys | SDK integration (React, Next.js, Vue) | In-app product feedback |
Link surveys work out of the box. Website and app surveys require embedding the Formbricks SDK in your frontend code.
Configuration
Custom Branding
Under Organization Settings → Branding, customize:
- Logo and favicon
- Primary color
- Background color
- Survey URL slug (e.g.,
forms.example.com/s/your-brand)
Webhooks
Forward survey responses to external services. Under Integrations → Webhooks:
https://n8n.example.com/webhook/formbricks-response
Pair with n8n or Activepieces for automated workflows — send responses to Slack, create tickets, update spreadsheets.
Response Notifications
Configure email notifications per survey — get notified on every response or on a daily/weekly digest. Requires SMTP configuration.
Reverse Proxy
Formbricks runs on port 3000. For production, put it behind an SSL-terminating reverse proxy.
Caddy:
forms.example.com {
reverse_proxy formbricks:3000
}
Critical: WEBAPP_URL and NEXTAUTH_URL must both match your public URL exactly (including https://). Mismatches cause silent authentication failures.
See Reverse Proxy Setup for Nginx and Traefik configs.
Backup
PostgreSQL holds all survey definitions and responses:
docker exec formbricks-db pg_dump -U formbricks formbricks > formbricks-backup.sql
Redis data is cache — not critical to back up. See Backup Strategy for scheduling.
Troubleshooting
Login page loads but authentication fails silently
Symptom: Clicking login does nothing, or you get redirected back to the login page.
Fix: WEBAPP_URL and NEXTAUTH_URL must be identical and must match the URL you’re accessing in the browser. If you access https://forms.example.com but set http://forms.example.com (no s), auth will fail. Check both variables.
”Cannot connect to database” on startup
Symptom: Formbricks container restarts repeatedly with database connection errors.
Fix: PostgreSQL must be healthy before Formbricks starts. The health check in the compose file handles this, but if you see issues:
docker logs formbricks-db
Check that the password in DATABASE_URL matches POSTGRES_PASSWORD.
Invitation emails not sending
Symptom: Team members don’t receive invitation emails.
Fix: SMTP must be configured. Without it, Formbricks can’t send any emails. Test your SMTP settings:
docker exec formbricks env | grep SMTP
Verify the host, port, and credentials are correct. Many SMTP providers require an app password, not your login password.
Surveys load slowly
Symptom: Survey pages take 5+ seconds to load for respondents.
Fix: Ensure Redis is running and connected. Without Redis, Formbricks falls back to slow database queries for caching. Check Redis connectivity:
docker exec formbricks-redis valkey-cli ping
Should return PONG.
Formbricks vs Google Forms
| Feature | Formbricks | Google Forms |
|---|---|---|
| Conditional logic | Yes (complex branching) | Basic (go to section) |
| Custom branding | Full control | Google branding |
| Response analytics | Built-in dashboards | Basic charts |
| Data ownership | Your server | Google’s servers |
| Website popups | Yes (JS widget) | No |
| In-app surveys | Yes (SDK) | No |
| Webhooks | Yes | No |
| Price | Free (self-hosted) | Free (Google-hosted) |
| File uploads | Yes | Yes |
| NPS surveys | Yes | No (manual) |
| API access | Full REST API | Google Sheets API |
Verdict
Formbricks is the most capable self-hosted form builder available. It goes beyond basic form creation — the website widget, in-app SDK, and conditional logic make it a real alternative to Typeform and even product feedback tools like Hotjar. The analytics dashboards mean you don’t need to export to a spreadsheet to understand your data.
Use Formbricks if: You need forms with logic branching, in-app surveys, or website popups. Particularly strong for product teams collecting user feedback.
Look elsewhere if: You just need a simple poll or voting tool — Rallly (scheduling polls) or LimeSurvey (academic surveys) are simpler. If you need a feature-request board, see Fider.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments