In this guide we show how to deploy EdgeDB using a Fly.io PostgreSQL cluster as the backend. The deployment consists of two apps: one running Postgres and the other running EdgeDB.
At the moment, it isn’t possible to expose Fly-hosted EdgeDB instances to the public internet, only internally to other Fly projects. As such your application must also be hosted on Fly.
flyctl CLI (install)
Every Fly.io app must have a globally unique name, including service VMs like
Postgres and EdgeDB. Pick a name and assign it to a local environment variable
EDB_APP. In the command below, replace
myorg-edgedb with a name
of your choosing.
flyctl apps create --name $EDB_APP
New app created: myorg-edgedb
Now let’s use the
read command to securely assign a value to the
PASSWORD environment variable.
echo -n "> " && read -s PASSWORD
Now let’s assign this password to a Fly secret, plus a few other secrets that we’ll need. There are a couple more environment variables we need to set:
flyctl secrets set \ EDGEDB_PASSWORD="$PASSWORD" \ EDGEDB_SERVER_BACKEND_DSN_ENV=DATABASE_URL \ EDGEDB_SERVER_TLS_CERT_MODE=generate_self_signed \ EDGEDB_SERVER_PORT=8080 \ --app $EDB_APP
Secrets are staged for the first deployment
Let’s discuss what’s going on with all these secrets.
EDGEDB_SERVER_BACKEND_DSN_ENV tells the EdgeDB container where to
look for the PostgreSQL connection string (more on that below)
EDGEDB_SERVER_TLS_CERT_MODE tells EdgeDB to auto-generate a
self-signed TLS certificate.
You may instead choose to provision a custom TLS certificate. In this
case, you should instead create two other secrets: assign your certificate
EDGEDB_SERVER_TLS_CERT and your private key to
EDGEDB_SERVER_PORT tells EdgeDB to listen on port 8080 instead
of the default 5656, because Fly.io prefers
8080 for its default health
Finally, let’s scale the VM as EdgeDB requires a little bit more than the default Fly.io VM side provides:
flyctl scale vm shared-cpu-1x --memory=1024 --app $EDB_APP
Scaled VM Type to shared-cpu-1x CPU Cores: 1 Memory: 1 GB
Now we need to provision a PostgreSQL cluster and attach it to the EdgeDB app.
If you have an existing PostgreSQL cluster in your Fly.io organization, you can skip to the attachment step.
Then create a new PostgreSQL cluster. This may take a few minutes to complete.
flyctl pg create --name $PG_APP --vm-size shared-cpu-1x
? Select region: sea (Seattle, Washington (US)) ? Specify the initial cluster size: 1 ? Volume size (GB): 10 Creating postgres cluster myorg-postgres in organization personal Postgres cluster myorg-postgres created Username: postgres Password: <random password> Hostname: myorg-postgres.internal Proxy Port: 5432 PG Port: 5433 Save your credentials in a secure place, you won't be able to see them again! Monitoring Deployment ... --> v0 deployed successfully
In the output, you’ll notice a line that says
Machine <machine-id> is
created. The ID in that line is the ID of the virtual machine created for
your Postgres cluster. We now need to use that ID to scale the cluster since
shared-cpu-1x VM doesn’t have enough memory by default. Scale it with
flyctl machine update <machine-id> --memory 512 --app $PG_APP -y
Searching for image 'flyio/postgres:14.6' remotely... image found: img_0lq747j0ym646x35 Image: registry-1.docker.io/flyio/postgres:14.6 Image size: 361 MB Updating machine <machine-id> Waiting for <machine-id> to become healthy (started, 3/3) Machine <machine-id> updated successfully! ==> Monitoring health checks Waiting for <machine-id> to become healthy (started, 3/3) ...
With the VM scaled sufficiently, we can now attach the PostgreSQL cluster to the EdgeDB app:
flyctl pg attach "$PG_APP" \ --database-user "$PG_ROLE" \ --app $EDB_APP
Postgres cluster myorg-postgres is now attached to myorg-edgedb The following secret was added to myorg-edgedb: DATABASE_URL=postgres://...
Lastly, EdgeDB needs the ability to create Postgres databases and roles, so let’s adjust the permissions on the role that EdgeDB will use to connect to Postgres:
echo "alter role \"$PG_ROLE\" createrole createdb; \quit" \ | flyctl pg connect --app $PG_APP
... ALTER ROLE
Everything is set! Time to start EdgeDB.
flyctl deploy --image=edgedb/edgedb \ --remote-only --app $EDB_APP
... 1 desired, 1 placed, 1 healthy, 0 unhealthy --> v0 deployed successfully
That’s it! You can now start using the EdgeDB instance located at
edgedb://myorg-edgedb.internal in your Fly.io apps.
If deploy did not succeed:
make sure you’ve scaled the EdgeDB VM
check the logs for more information:
flyctl logs --app $EDB_APP
Now we need to persist the auto-generated TLS certificate to make sure it survives EdgeDB app restarts. (If you’ve provided your own certificate, skip this step).
flyctl ssh console --app $EDB_APP -C \ "edgedb-show-secrets.sh --format=toml $EDB_SECRETS" \ | tr -d '\r' | flyctl secrets import --app $EDB_APP
Let’s construct the DSN (AKA “connection string”) for our instance. DSNs have
the following format:
can construct the DSN with the following components:
<username>: the default value —
<password>: the value we assigned to
<hostname>: the name of your EdgeDB app (stored in the
$EDB_APP environment variable) suffixed with
.internal. Fly uses this
synthetic TLD to simplify inter-app communication. Ex:
8080, which we configured earlier
We can construct this value and assign it to a new environment variable called
Consider writing it to a file to ensure the DSN looks correct. Remember to
delete the file after you’re done. (Printing this value to the terminal with
echo is insecure and can leak your password into shell logs.)
echo $DSN > dsn.txt
To connect to this instance from another Fly app (say, an app that runs your
API server) set the value of the
EDGEDB_DSN secret inside that app.
flyctl secrets set \ EDGEDB_DSN=$DSN \ --app my-other-fly-app
We’ll also set another variable that will disable EdgeDB’s TLS checks. Inter-application communication is secured by Fly so TLS isn’t vital in this case; configuring TLS certificates is also beyond the scope of this guide.
flyctl secrets set EDGEDB_CLIENT_TLS_SECURITY=insecure \ --app my-other-fly-app
You can also set these values as environment variables inside your
fly.toml file, but using Fly’s built-in secrets functionality is recommended.
If you need to access EdgeDB from outside the Fly.io network, you’ll need to configure the Fly.io proxy to let external connections in.
First, save the EdgeDB app config in an empty directory:
flyctl config save -a $EDB_APP
fly.toml file will be created upon result. Let’s make sure our
[[services]] section looks something like this:
[[services]] http_checks =  internal_port = 8080 processes = ["app"] protocol = "tcp" script_checks =  [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] port = 5656 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
In the same directory, redeploy the EdgeDB app.
This makes the EdgeDB port available to the outside world. You can now
access the instance from any host via the following public DSN:
To secure communication between the server and the client, you will also
need to set the
EDGEDB_TLS_CA environment secret in your application.
You can securely obtain the certificate content by running:
flyctl ssh console -a $EDB_APP \ -C "edgedb-show-secrets.sh --format=raw EDGEDB_SERVER_TLS_CERT"
Once it’s up and running, use
edgedb instance link to create a local
alias to the remote instance.
edgedb instance link \ --trust-tls-cert \ --dsn $DSN \ --non-interactive \ fly
Authenticating to edgedb://email@example.com:5656/edgedb Successfully linked to remote instance. To connect run: edgedb -I fly
You can now run CLI commands against this instance by specifying it by name
-I fly; for example, to apply migrations:
The command groups
edgedb instance and
edgedb project are not
intended to manage production instances.
edgedb -I fly migrate
Using an HTTP client, you can perform health checks to monitor the status of your EdgeDB instance. Learn how to use them with our health checks guide.