Managoat is the hosted Fountain. Fountain is the open-source engine, and its name is on the CLI, the API, the SDK and this manual. Everything here applies to Managoat unless a page says it is for a self-hosted server.
Deploy on Coolify
Coolify runs on a server you own, and it deploys a Docker Compose file from a git repository. Fountain ships one, so Coolify needs no file of its own here. This guide shows you which five values to set in the Coolify interface. It then shows you the two compose defaults that a public server must not keep.
Dokploy works the same way. The values below apply there too.
For a plain Docker host with no interface in front of it, read
Deploy an instance. Coolify runs the same
docker-compose.yml,
so the two paths differ in the interface and not in the result.
Before you start
You need a Coolify server, and a domain that points at it.
Generate the two keys now. You paste them in a later step.
openssl rand -base64 48 | tr -d '\n' # SECRET_KEY_BASE
openssl rand 32 | base64 | tr '+/' '-_' | tr -d '=\n' # MASTER_SECRETS_KEY
Back MASTER_SECRETS_KEY up before you have data. It is not in the database.
A database backup alone does not protect you. Read
Back up and restore.
You also need a sandbox provider token. Read Self-host Fountain for what each provider needs.
Create the resource
In Coolify, select New, then Docker Compose. Point it at
https://github.com/BinaryBourbon/fountain, on the main branch, with
docker-compose.yml as the compose file.
Coolify reads the file and lists the environment variables in it. Every variable has a default that works, except the ones below.
Set the five values
SECRET_KEY_BASE |
The first key above. |
MASTER_SECRETS_KEY |
The second key above. |
SPRITES_TOKEN |
Your sandbox provider token. The app starts without one, and every conversation then fails. |
POSTGRES_PASSWORD |
A long random string. The default is postgres, and the next section says why that matters. |
PUBLIC_URL |
The address you gave the app service, with the scheme. |
PUBLIC_URL is the one that catches people. Its compose default is
http://localhost:4000, and that default is a value, not an absence. The app
starts, and every verification email and every sandbox then holds a localhost
address. Set it to the domain in the app service's Domains field, and
include https://.
The compose file does not use Coolify's SERVICE_FQDN_ variables, which fill
a domain in for you. Docker Compose on its own resolves an unset variable to
an empty string, and an empty PUBLIC_URL is a value that a production boot
refuses. One file serves both paths, so you type the domain twice.
Close the two ports
The compose file publishes two ports on the host. That suits a laptop. It does not suit a server on the internet.
ports:
- "${POSTGRES_HOST_PORT:-5432}:5432" # postgres
- "${PORT:-4000}:4000" # app
Postgres is the one that matters. A server with an open firewall offers
Postgres to the internet on 5432, and the compose default password is
postgres. Set POSTGRES_PASSWORD, and block 5432 at the firewall. Coolify
does not manage the host firewall for you.
The app port needs no host publication either. Coolify's proxy reaches the container over the compose network, and the Domains field is what routes traffic to it.
Trust the proxy
Coolify puts a proxy in front of the app, so the app sees the proxy and not the caller. Left unset, Fountain falls back to cluster ranges that match nothing here. Every per-IP rate-limit bucket then collapses into one, and every audit row records the proxy's address.
TRUSTED_PROXIES=172.16.0.0/12
That range covers the Docker bridge networks Coolify creates. Narrow it when you confirm the address that the proxy forwards from.
Deploy
Select Deploy. The first deploy takes a few minutes, because the app applies the database migrations before it opens a listener.
The app service carries a health check, so Coolify reports the container as healthy only after the migrations finish.
Register the first account
Open your domain and register. The compose defaults are EMAIL_DELIVERY=none
and FIRST_USER_ADMIN=true, so your account self-verifies and becomes the
admin.
Register before you give the URL to anybody. While no admin exists, the first verified account takes the role.
Then set REGISTRATION_ENABLED=false and deploy again.
What Coolify does not do for you
- It runs one instance. Fountain clusters over Erlang distribution, and the compose file describes a single container. A second replica is not a second node, and two schedulers then race over the same sandboxes. Read Architecture.
- It takes no database backup. The compose file has a
backupprofile that dumps Postgres nightly, and Coolify does not start a profile. Use Coolify's own scheduled backups for the Postgres service instead. Read Back up and restore for what a restore needs, and remember that a dump alone cannot decrypt itself. - It does not pin the version for you. The compose file pins a release
tag, and a redeploy from
mainpicks up whatever tag the branch holds. Fork the repository, or setFOUNTAIN_IMAGE_TAG, and read Upgrade an instance before you move it. Migrations run at boot, and Fountain does not support a downgrade.