Deploying EdgeDB to Fly.io

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.

Prerequisites

  • Fly.io account

  • flyctl CLI (install)

Provision a Fly.io app for EdgeDB

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 called EDB_APP. In the command below, replace myorg-edgedb with a name of your choosing.

  1. $
  1. EDB_APP=myorg-edgedb
  1. $
  1. flyctl apps create --name $EDB_APP
  1. New app created: myorg-edgedb

Now let’s use the read command to securely assign a value to the PASSWORD environment variable.

  1. $
  1. 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:

  1. $
  1. flyctl secrets set \
  2. EDGEDB_PASSWORD="$PASSWORD" \
  3. EDGEDB_SERVER_BACKEND_DSN_ENV=DATABASE_URL \
  4. EDGEDB_SERVER_TLS_CERT_MODE=generate_self_signed \
  5. EDGEDB_SERVER_PORT=8080 \
  6. --app $EDB_APP
  1. Secrets are staged for the first deployment

Let’s discuss what’s going on with all these secrets.

  • The EDGEDB_SERVER_BACKEND_DSN_ENV tells the EdgeDB container where to look for the PostgreSQL connection string (more on that below)

  • The 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 to EDGEDB_SERVER_TLS_CERT and your private key to EDGEDB_SERVER_TLS_KEY.

  • Lastly, EDGEDB_SERVER_PORT tells EdgeDB to listen on port 8080 instead of the default 5656, because Fly.io prefers 8080 for its default health checks.

Finally, let’s scale the VM as EdgeDB requires a little bit more than the default Fly.io VM side provides:

  1. $
  1. flyctl scale vm shared-cpu-1x --memory=1024 --app $EDB_APP
  1. Scaled VM Type to
  2. shared-cpu-1x
  3. CPU Cores: 1
  4. Memory: 1 GB

Create a PostgreSQL cluster

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.

  1. $
  1. PG_APP=myorg-postgres
  1. $
  1. flyctl pg create --name $PG_APP --vm-size dedicated-cpu-1x
  1. ? Select region: sea (Seattle, Washington (US))
  2. ? Specify the initial cluster size: 1
  3. ? Volume size (GB): 10
  4. Creating postgres cluster myorg-postgres in organization personal
  5. Postgres cluster myorg-postgres created
  6. Username: postgres
  7. Password: <random password>
  8. Hostname: myorg-postgres.internal
  9. Proxy Port: 5432
  10. PG Port: 5433
  11. Save your credentials in a secure place, you won't be able to see them
  12. again!
  13. Monitoring Deployment
  14. ...
  15. --> v0 deployed successfully

Attach the PostgreSQL cluster to the EdgeDB app:

  1. $
  1. PG_ROLE=myorg_edgedb
  1. $
  1. flyctl pg attach \
  2. --postgres-app "$PG_APP" \
  3. --database-user "$PG_ROLE" \
  4. --app $EDB_APP
  1. Postgres cluster myorg-postgres is now attached to myorg-edgedb
  2. The following secret was added to myorg-edgedb:
  3. 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:

  1. $
  1. echo "alter role \"$PG_ROLE\" createrole createdb; \quit" \
  2. | flyctl pg connect $PG_APP
  1. ...
  2. ALTER ROLE

Start EdgeDB

Everything is set! Time to start EdgeDB.

  1. $
  1. flyctl deploy --image=edgedb/edgedb \
  2. --remote-only --app $EDB_APP
  1. ...
  2. 1 desired, 1 placed, 1 healthy, 0 unhealthy
  3. --> 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:

  1. make sure you’ve scaled the EdgeDB VM

  2. re-run the deploy command

  3. check the logs for more information: flyctl logs --app $EDB_APP

Persist the generated TLS certificate

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).

  1. $
  1. EDB_SECRETS="EDGEDB_SERVER_TLS_KEY EDGEDB_SERVER_TLS_CERT"
  1. $
  1. flyctl ssh console --app $EDB_APP -C \
  2. "edgedb-show-secrets.sh --format=toml $EDB_SECRETS" \
  3. | tr -d '\r' | flyctl secrets import --app $EDB_APP

Connecting to the instance

Let’s construct the DSN (AKA “connection string”) for our instance. DSNs have the following format: edgedb://<username>:<password>@<hostname>:<port>. We can construct the DSN with the following components:

  • <username>: the default value — edgedb

  • <password>: the value we assigned to $PASSWORD

  • <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: myorg-edgedb.internal.

  • <port>: 8080, which we configured earlier

We can construct this value and assign it to a new environment variable called DSN.

  1. $
  1. DSN=edgedb://edgedb:$PASSWORD@$EDB_APP.internal:8080

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.)

  1. $
  1. echo $DSN > dsn.txt
  1. $
  1. open dsn.txt
  1. $
  1. rm dsn.txt

From a Fly.io app

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.

  1. $
  1. flyctl secrets set \
  2. EDGEDB_DSN=$DSN \
  3. --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.

  1. $
  1. flyctl secrets set EDGEDB_CLIENT_TLS_SECURITY=insecure \
  2. --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.

From your local machine

To access the EdgeDB instance from local development machine/laptop, install the Wireguard VPN and create a tunnel, as described on Fly’s Private Networking docs.

Once it’s up and running, use edgedb instance link to create a local alias to the remote instance.

  1. $
  1. edgedb instance link \
  2. --trust-tls-cert \
  3. --dsn $DSN \
  4. --non-interactive \
  5. fly
  1. Authenticating to edgedb://edgedb@myorg-edgedb.internal:5656/edgedb
  2. Successfully linked to remote instance. To connect run:
  3. edgedb -I fly

You can now run CLI commands against this instance by specifying it by name with -I fly; for example, to apply migrations:

  1. $
  1. edgedb -I fly migrate