This only works with an Ubuntu machine, so ensure the underlying OS is verified beforehand!
This setup uses Traefik as a reverse proxy, essential for directing incoming traffic to the correct
container and enabling secure internet access to Formbricks. Traefik is chosen for its simplicity and
automatic SSL management via Letβs Encrypt.
The installer stores generated PostgreSQL, Hub, Cube, and AuthZed credentials in
./formbricks/.env and
restricts the file to 0600. PostgreSQL has a raw password for the database plus a URL-encoded companion for
connection strings. When bundled RustFS is enabled, its generated credentials are stored there too. Keep that
file private, include it in your server backup plan, and avoid checking it into source control or copying it to
shared locations.For better RustFS performance and stability, prefer local SSD or NVMe-backed storage for the host volume
behind
rustfs-data. Avoid NFS and other network filesystems for bundled RustFS data, and use XFS on
dedicated storage disks when you manage the host layout yourself.Requirements
- An Ubuntu Virtual Machine with SSH access.
- A custom domain with an A record pointing to your server.
- Ports 80 and 443 are open in your VMβs Security Group, allowing Traefik to create an SSL certificate.
Deployment
Run this command in your terminal:The v6 one-click stack is based on the production Docker Compose file and includes the Formbricks Hub API,
hub-worker, and Cube as part of the baseline (Cube configuration lives under formbricks/cube/). Ensure your
generated formbricks/docker-compose.yml contains the worker service and a non-empty HUB_API_KEY, and that
formbricks/.env contains CUBEJS_API_SECRET, AUTHZED_TOKEN, and AUTHZED_DATABASE_PASSWORD before
treating the stack as ready. The installer generates these values without printing them and restricts .env
to 0600. HUB_API_URL should normally stay at http://hub:8080. Bundled SpiceDB is installed for every new
setup and does not require an Enterprise license check.The v5 one-click Traefik setup also exposes Hub-backed FeedbackRecords through Formbricks at
/api/v3/feedbackRecords and /v1/feedback-records. Traefik calls the internal Formbricks gateway auth
endpoint first, then forwards allowed requests to Hub with the generated HUB_API_KEY. Browser callers should
request short-lived gateway tokens from /api/v3/gateway/token with { "service": "feedbackRecords" }.Script Prompts
During installation, the script will prompt you to provide some details:- Overwriting Docker GPG Keys: If Docker GPG keys already exist, the script will ask whether you want to overwrite them.
- Domain Name: Enter the domain name where youβll host Formbricks. The domain will be used to generate an SSL certificate. Do not include the protocol (http/https).
- HTTPS Certificate Setup:
The script will ask if youβd like to create an HTTPS certificate for your domain. Enter
Yto proceed (highly recommended for secure access).
- DNS Setup Prompt: Ensure that your domainβs DNS is correctly configured and ports 80 and 443 are open. Confirm this by entering
Y. This step is crucial for proper SSL certificate issuance and secure server access.
- Email Address for SSL Certificate: Provide an email address to register the SSL certificate. Notifications regarding the certificate will be sent to this address.
- Enforce HTTPS with HSTS:
Enabling HTTP Strict Transport Security (HSTS) ensures all communication with your server is encrypted. Itβs a recommended best practice. Enter
Yto enforce HTTPS.
- Email Service Setup Prompt: The script will ask if you want to set up the email service. EnterΒ
YΒ to proceed.(default isΒN). You can skip this step if you donβt want to set up the email service. You will still be able to use Formbricks without setting up the email service.
Update
To update Formbricks for a minor or patch release, first go to the directory that contains yourformbricks/ folder. Download the current stable updater there, replacing any older formbricks.sh, and
then run it:
hub-worker is missing, then pulls images and runs the read-only AuthZed upgrade check. A failed preflight leaves
the existing application running.
Otherwise it stops the stack, waits for PostgreSQL, completes application migrations, and only then starts the
new stack. A failed migration leaves the stack stopped for recovery; preparation is never run against a live
installation by the updater.
Once those checks pass, the update also publishes the Formbricks containerβs port 3000 on 127.0.0.1 only, if
your docker-compose.yml or your Compose override file (such as docker-compose.override.yml) still publishes it on
every interface (- 3000:3000). Traefik reaches Formbricks over the Compose network and keeps serving it on ports
80 and 443, so outside traffic always passes through Traefik. Each file it changes is kept as
<file>.before-loopback-port. Before stopping anything, it renders the Compose files exactly as Docker Compose will
load them and checks that they publish port 3000 once, on 127.0.0.1; if not, it restores the files it changed and
continues the update with the port as it was. A mapping with an address you chose, such as - 0.0.0.0:3000:3000, is
left as it is, and so is everything when .env sets COMPOSE_FILE. On Docker Engine before 28.0, and on 28.2.0 to
28.3.2, other machines on your local network can still reach a port published on 127.0.0.1, so the installer and
the update warn you to upgrade Docker.
Starting with v5.4, the updater also recognizes the old amd64-only bundled Valkey digest. It backs up your
Compose file, replaces only that exact image reference with the native amd64/arm64 digest, and validates the
result before pulling. An already-updated or custom Valkey image is left unchanged. The named redis volume
and its AOF data are preserved.
While the stack is stopped, the updater also refreshes the bundled Cube model (cube/cube.js and
cube/schema/FeedbackRecords.js), so analytics charts can use members a release adds. It downloads the files
of the release your Formbricks image runs: the stable branch for latest, or the tag the image is pinned to.
It keeps the previous files in cube/previous/. The two files change together: if either cannot be
downloaded, backed up or replaced, both stay as they were, the update finishes, and the updater prints the
command to retry, ./formbricks.sh refresh-cube. An image pinned to anything else, such as a digest, leaves
both files unchanged.
Existing one-click installations keep the database credentials in their local docker-compose.yml or .env.
The update command does not regenerate or rotate them.
Add SpiceDB to an Existing One-Click Installation
The update command intentionally preserves your customized Compose file, so it cannot add SpiceDB by itself. Before upgrading to a release that uses AuthZed:- Follow the maintenance upgrade guide: stop writers and controllers, drain in-flight work, then back up configuration, secrets, and databases.
-
Download the release-matched
authzed-postgres-bootstrap.shinto theformbricksdirectory. -
Generate and add
AUTHZED_TOKENandAUTHZED_DATABASE_PASSWORDto.envusingopenssl rand -hex 32. -
Merge
authzed-db-bootstrap,spicedb-migrate,spicedb,authzed-initialize, and the profiledauthzed-opsservice from the released Compose file while preserving installer-added Traefik, storage, and mail configuration. Add the six application variables and useAUTHZED_CONSISTENCY=fully_consistent. -
Validate the target Compose file privately and pull the pinned images from the
formbricksdirectory. Keep maintenance active and writers stopped. -
Wait for the datastores, then run migrations, preparation, and verification using the target image:
A mismatched non-empty schema requires the reviewed digest described in the maintenance guide.
-
If preparation exits
0, addFORMBRICKS_AUTHZED_V6_MIGRATION_ACKNOWLEDGED=trueto.envand run./formbricks.sh update. Do not bypass a blocked check. Keep maintenance active until access tests pass. -
Verify
authzed-db-bootstrap,spicedb-migrate, andauthzed-initializecompleted andspicedbis healthy. -
Back up the authorization database with
docker compose exec -T postgres pg_dump -U postgres -d spicedb > spicedb-backup.sqland add it to your regular backup procedure.
docker compose down -v during this migration or rollback because the existing PostgreSQL volume
stores both Formbricks and SpiceDB data.
For upgrades, restoration, schema changes, and relationship repair, follow the canonical
AuthZed Operations guide.
Stop
To stop Formbricks, simply run the following command:Restart
To restart Formbricks, simply run the following command:Cleanup RustFS init (optional)
During the one-click setup, a temporaryrustfs-init service configures RustFS (bucket, policy, service
user). It is idempotent and safe to leave in place; it will do nothing on subsequent starts once the
configuration exists.
If you prefer to remove the rustfs-init service and its references after a successful setup, run:
./formbricks.sh cleanup-minio-init is still available as a backward-compatible alias.
This only removes the init job and its Compose references; it does not delete any data or affect your RustFS
configuration.
Uninstall
To uninstall Formbricks, simply run the following command, but keep in mind that this will delete all your data!Debug
If you encounter any issues, you can check the logs of the containers with:Troubleshooting
If you encounter any issues, consider the following steps:- Inbound Rules: Make sure you have added inbound rules for Port 80 and 443 in your VMβs Security Group.
- A Record: Verify that you have set up an A record for your domain, pointing to your VMβs IP address.
-
Check Docker Instances: RunΒ
docker psΒ to check the status of the Docker instances. -
Check Formbricks Logs: RunΒ
cd formbricks && docker compose logsΒ to check the logs of the Formbricks stack.