This repository contains code and configuration related to Digitale Gesellschaft's survey tool available under
forms.digitale-gesellschaft.ch.
We rely on Formbricks which we host on Fly.
Sensitive configuration data is stored via Fly secrets. Currently this includes the following environment variables:
CRON_SECRET1DATABASE_URLENCRYPTION_KEY2NEXTAUTH_SECRET3REDIS_URLS3_ACCESS_KEYS3_SECRET_KEYSMTP_PASSWORDSMTP_USER
-
The Fly app is named
digiges-forms, currently runs on a singleshared-cpu-1xinstance with512 MBRAM4 and is hosted in the Frankfurt, Germany (fra) region. -
The
digiges-formsapp connects to theformbricksPostgreSQL database on ourpg-digigesAiven service hosted on DigitalOcean in the Frankfurt, Germany (fra) region.Note that Aiven's Postgres cluster TLS certificates are signed by its own private CA, so we have to manually specify the right certificate file when connecting, e.g.:
PGSSLROOTCERT=aiven.io_ca.pem psql --dbname=$(grep -Po "(?<=^DATABASE_URL=').+(?='$)" .secrets) -
Formbricks requires a Redis-compatible key value store, even for a single-machine deployment. We use Valkey, managed by Aiven as service
valkey-digiges, hosted on DigitalOcean in the Frankfurt, Germany (fra) region. -
Formbricks also requires an S3-compatible5 object storage bucket to store static user file uploads. We use a Tigris bucket named
digiges-formsattached to our Fly app. -
To cope with higher demand when conducting surveys, we can increase RAM and/or switch to a faster CPU as needed6. It's recommended to allocate at least
1024 MBRAM before running any serious survey.We could also scale horizontally, i.e. run multiple instances of Formbricks, even in multiple regions.
We can directly connect to the digiges-forms app via an SSH tunnel to perform any low-level administration tasks.
To do so, run:
flyctl ssh console --app digiges-formsTo deploy a new digiges-forms release on Fly, follow these steps:
-
Create a local snapshot of the database, see below.
-
Set the desired
ghcr.io/formbricks/formbrickstag in theDockerfile. -
Update the Formbricks configuration in
fly.toml's[env]section and -- for sensitive information -- in the app's Fly secrets if necessary.Documentation of all the environment variables Formbricks supports for configuration should be found in the docs. If something is missing, the following resources should help:
- File
turbo.jsonlists all supported env vars without further info. Use GitHub's compare view to compare the desired formbricks release tag with the one that is currently deployed. To e.g. show the diffs between version 4.0.0 and 4.0.1, use https://github.com/formbricks/formbricks/compare/4.0.0...4.0.1#files_bucket. - File
.env.examplecontains example configuration.
- File
-
Build and deploy the image:
just deploy
-
Consult the official migration guide. For Formbricks 4.x and above, all database migrations should be done automatically without any further action necessary.
To create a full dump of the formbricks PostgreSQL database, run the following:
just backup(You need the Git-ignored .secrets file for the above to work.)
To restore the formbricks PostgreSQL database from the latest local dump created via just backup, run the following:
just restoreAlternatively, you can restore an explicit dump via the recipe's datetime parameter:
just restore '2025-11-11T04:20:49+01:00'(You need the Git-ignored .secrets file for the above to work.)
Code and configuration in this repository are licensed under AGPL-3.0-or-later. See
LICENSE.md.
Footnotes
-
Mustn't exceed 256 bits / 32 bytes in binary representation. ↩
-
Mustn't exceed 256 bits / 32 bytes in binary representation. ↩
-
Mustn't exceed 256 bits / 32 bytes in binary representation. ↩
-
Especially the first start after a new deployment turned out to be memory-intensive (probably the Prisma Client performing the DB migrations): With 256 MiB RAM, the app used to crash reproducibly, so we increased this to 512 MiB. ↩
-
Note that we can't use Backblaze B2 since its S3-compatible API doesn't implement the POST Object operation that Formbricks uses to upload files. ↩
-
Note that scaling automatically restarts the app. The most relevant documentation on (auto)scaling Fly apps includes:
↩