EdgeDB on a VPS: Don't do what I did
Tags: docker, edgedb, devops, cloud
Published: 2023-01-08 21:02:45

So I've spent all day trying to have my Docker container connect to EdgeDB today and I think I've cracked it. I'm sure some other people have been just as confused as me so I thought I'd share my findings so far.

My goal was to setup my VPS with a scraper running in a Docker container which writes data to my EdgeDB database.

## edgedb driving me mad 😤

Through SSH, I created my EdgeDB instance on a non-root user with `edgedb instance create`, performed my migrations and I thought everything was fine.

Coming back to the scraper later, I came to find that for the whole time I was away my scraper couldn't connect to EdgeDB.

I was receiving a `ClientConnectionFailedError` saying `cannot establish connection: Connection refused`.

So I whipped open the server's `edgedb` cli and tried to connect. It worked fine. I look back at my scraper container's logs and it's able to connect again.

*I was absolutely befuddled.*

Tried playing around with the server's CLI to replicate the error I'd seen in my scraper, nothing.

Hmm, maybe it's an issue with docker. I found the `edgedb/edgedb` Docker image with a built-in `edgedb` CLI. Could replicate the issue with that either.

*Everything was working while I was logged in, but as soon as I logged out the client would fail to connect.*

I felt like I was going crazy (Life as a Developer™️).

I was scouring through the docs once again, and the problem suddenly clicked in my mind.

## feeling both 😞 and 🤩

I'd already looked at it sooo many times, but [this](https://www.edgedb.com/docs/guides/deployment/bare_metal) wonderful piece of documentation had a critical piece that I'd missed.

I thought that the DB instances ran globally, but it turns out that using `edgedb instance create` makes instances that are scoped to the user executing the command.

Following the guide more closely, I noticed that `edgedb instance create` is never used!

The key was to use the global `systemd` daemon thing instead:

```sh
sudo systemctl enable --now edgedb-server-2
```

This serves a global instance on port `5656`. It's independent of user and always runs in the background.

Set a password for the `edgedb` credentials:

```sh
echo -n "> " && read -s PASSWORD

sudo edgedb --port 5656 --tls-security insecure --admin query \
 "ALTER ROLE edgedb SET password := '$PASSWORD'"
```

Now you can go ahead and link it to your CLI so it's easier to connect in future. If you've kept the default settings, the command is:

```sh
edgedb instance link \
  --host localhost \
  --port 5656 \
  --user edgedb \
  --database edgedb \
  --trust-tls-cert \
  my-instance
```

You'll be prompted to enter in that same password and bob's your uncle!

You can now easily connect through the CLI:

```sh
edgedb -I my-instance
```

The DSN is a connection string of the format `edgedb://username:password@host/database`. To get the DSN made during your linking, do:

```sh
edgedb instance credentials -I my-instance --insecure-dsn
```

Check it works through the CLI without requiring the link:

```sh
edgedb --dsn my-dsn --tls-security insecure 
```

Then you can use that DSN as the connection config for your client as I did with my Docker container. Whether it's Docker or not, set the environment variable `EDGEDB_DSN`.

```sh
EDGEDB_DSN="my-dsn?tls_security=insecure"
```

> Make sure you have the `?tls_security=insecure` param in the `EDGEDB_DSN` environment variable for your runtime client. **Notice the `_` rather than the `-` we used earlier.** Here's more about the DSN [in the docs](https://www.edgedb.com/docs/intro/clients#using-edgedb-dsn), although right now these aren't respected in the CLI.

Tada! 🥳

## outro 🎶

Thanks for reading through and I really hope this helped you so you're not banging your head against a metaphorical brick wall for as long as I was!

Let me know if you have any issues with this, I'd be keen to learn more about it.

On that note, I'll be getting rid of all that nasty `insecure` stuff by setting up the TLS certificates properly at some point. If you'd like to hear about that then let me know!