Skip to content

Commit

Permalink
docs: add supabase guide (#297)
Browse files Browse the repository at this point in the history
* docs: add supabase guide

* feat: add support for external connection poolers

* chore: use .env symlink in database package

* chore: remove database .env.example

* docs: finish supabase pooling section

* docs: fix small typo

* docs: replace prisma with app wording

* docs: fix up supabase pooling section

* fix: deleted too much in contributing docs

* docs: change pooling heading

* docs: reduce linux shaming

* docs: include direct connection url in fly.io
  • Loading branch information
nicktrn authored Aug 11, 2023
1 parent beef776 commit 603ffbc
Show file tree
Hide file tree
Showing 17 changed files with 87 additions and 17 deletions.
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ SESSION_SECRET=abcdef1234
MAGIC_LINK_SECRET=abcdef1234
ENCRYPTION_KEY=ae13021afef0819c3a307ad487071c06 # Must be a random 16 byte hex string. You can generate an encryption key by running `openssl rand -hex 16` in your terminal
LOGIN_ORIGIN=http://localhost:3030
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres?schema=public
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres?schema=public
# This sets the URL used for direct connections to the database and should only be needed in limited circumstances
# See: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#fields:~:text=the%20shadow%20database.-,directUrl,-No
DIRECT_URL=${DATABASE_URL}
REMIX_APP_PORT=3030
APP_ENV=development
APP_ORIGIN=http://localhost:3030
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ jobs:
# Setup environment variables
cp ./.env.example ./.env
cp ./examples/nextjs-test/.env.example ./examples/nextjs-test/.env.local
cp ./packages/database/.env.example ./packages/database/.env
# Build packages
pnpm run build --filter @examples/nextjs-test^...
Expand Down
7 changes: 3 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ branch are tagged into a release monthly.
```
pnpm i
```
4. Create your `.env` files
4. Create your `.env` file
```
cp .env.example .env && cp packages/database/.env.example packages/database/.env
cp .env.example .env
```
5. Open the root `.env` file and generate a new value for `ENCRYPTION_KEY`:
5. Open it and generate a new value for `ENCRYPTION_KEY`:

`ENCRYPTION_KEY` is used to two-way encrypt OAuth access tokens and so you'll probably want to actually generate a unique value, and it must be a random 16 byte hex string. You can generate one with the following command:

Expand Down Expand Up @@ -178,7 +178,6 @@ To run the end-to-end tests, follow the steps below:
```sh
cp ./.env.example ./.env
cp ./examples/nextjs-test/.env.example ./examples/nextjs-test/.env.local
cp ./packages/database/.env.example ./packages/database/.env
```

2. Set up dependencies
Expand Down
1 change: 1 addition & 0 deletions apps/webapp/app/db.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function getClient() {
datasources: {
db: {
url: DATABASE_URL,
// We can't set directUrl here, and we don't have to
},
},
log: [
Expand Down
1 change: 1 addition & 0 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SecretStoreOptionsSchema } from "./services/secrets/secretStore.server"
const EnvironmentSchema = z.object({
NODE_ENV: z.union([z.literal("development"), z.literal("production"), z.literal("test")]),
DATABASE_URL: z.string(),
DIRECT_URL: z.string(),
SESSION_SECRET: z.string(),
MAGIC_LINK_SECRET: z.string(),
ENCRYPTION_KEY: z.string(),
Expand Down
1 change: 1 addition & 0 deletions apps/webapp/app/services/worker.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function getWorkerQueue() {
connectionString: env.DATABASE_URL,
concurrency: 5,
pollInterval: 1000,
noPreparedStatements: env.DATABASE_URL !== env.DIRECT_URL,
},
schema: workerCatalog,
recurringTasks: {
Expand Down
1 change: 1 addition & 0 deletions docker/dev-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ services:
- db
environment:
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
DIRECT_URL: postgres://postgres:postgres@db:5432/postgres?schema=public
SESSION_SECRET: secret123
MAGIC_LINK_SECRET: secret123
REMIX_APP_PORT: 3030
Expand Down
19 changes: 17 additions & 2 deletions docs/documentation/guides/self-hosting/flyio.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ You should fork the repository before starting so you can make changes and commi
brew install flyctl
```

```sh Linux
curl -L https://fly.io/install.sh | sh
```

```sh Windows
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
```
Expand All @@ -41,6 +45,8 @@ fly launch

2. Follow the prompts by `fly launch` and make sure to answer them in the following way:

<Warning>Do NOT get rid of your terminal output, we will need your database connection string shortly.</Warning>

```sh
? Would you like to copy its configuration to the new app? Yes
? Choose an app name (leaving blank will default to 'trigger-v2-fly-demo') <enter your preferred app name here or leave blank>
Expand All @@ -54,18 +60,26 @@ fly launch

### Required

`MAGIC_LINK_SECRET`, `SESSION_SECRET` and `ENCRYPTION_KEY`
1. `MAGIC_LINK_SECRET`, `SESSION_SECRET` and `ENCRYPTION_KEY`

All of these secrets should be 16-byte random strings, which you can easily generate (and copy into your pasteboard) with the following command:

```sh
openssl rand -hex 16 | pbcopy
```

`LOGIN_ORIGIN` and `APP_ORIGIN`
2. `LOGIN_ORIGIN` and `APP_ORIGIN`

Both of these secrets should be set to the base URL of your fly application. For example `https://trigger-v2-fly-demo.fly.dev`

3. `DIRECT_URL`

This needs to be set to the database connection string that was printed to your terminal after the creation step above:

```sh
Connection string: postgres://postgres:<PASSWORD>@<fly db name>.flycast:5432
```

### Optional

`AUTH_GITHUB_CLIENT_ID` and `AUTH_GITHUB_CLIENT_SECRET`
Expand Down Expand Up @@ -97,6 +111,7 @@ fly secrets set \
SESSION_SECRET=<random string> \
LOGIN_ORIGIN="https://<fly app name>.fly.dev" \
APP_ORIGIN="https://<fly app name>.fly.dev" \
DIRECT_URL="postgres://postgres:<PASSWORD>@<fly db name>.flycast:5432" \
FROM_EMAIL="Acme Inc. <hello@yourdomain.com>" \
REPLY_TO_EMAIL="Acme Inc. <reply@yourdomain.com>" \
RESEND_API_KEY=<your API Key> \
Expand Down
47 changes: 43 additions & 4 deletions docs/documentation/guides/self-hosting/supabase.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ ENCRYPTION_KEY=1189c93e399856a2a9a1454496171b2e
<img src="/images/supabase-project-setup.png" alt="Supabase - Project Setup" />
</Frame>

5. Navigate to Project `Settings -> Database` and copy your database connection string
5. Navigate to `Project Settings -> Database` and copy your database connection string

<Frame>
<img src="/images/supabase-db-url.png" alt="Supabase - Database URL" />
Expand Down Expand Up @@ -82,6 +82,7 @@ SESSION_SECRET=8d92078940c89588fc8b6f5481f2c6e0
ENCRYPTION_KEY=1189c93e399856a2a9a1454496171b2e

DATABASE_URL=postgresql://postgres:<PASSWORD>@db.<ID>.supabase.co:5432/postgres?schema=triggerdotdev
DIRECT_URL=${DATABASE_URL}

NODE_ENV=development
RUNTIME_PLATFORM=docker-compose
Expand Down Expand Up @@ -136,15 +137,53 @@ docker compose up

8. Congratulations, you're all set up and ready to go with Supabase and Docker! 🚀

{/* TODO: add pooling setup */}

## Bonus: Connection pooling

### What is connection pooling?

<Frame caption="Connection Pool - © 2023 Supabase, Apache License 2.0">
<img src="/images/supabase-connection-pool.png" alt="Supabase - Connection Pool" />
</Frame>

...coming soon!
When running on a single server, our app can be trusted to manage its own connections - it knows how many are open and can process its internal queue as needed.

<Tooltip tip="🐝">Serverless</Tooltip> changes things. Here, many concurrent app instances are started, each unaware of the others' connections. This can lead to a huge - potentially fatal - increase in connections straight to your DB.

<Info>
PostgreSQL has a [default connection limit](https://www.postgresql.org/docs/current/runtime-config-connection.html#:~:text=at%20server%20start.-,max_connections,-(integer)) of 100.
</Info>

**External connection pools** solve this by putting an additional layer between client and server, which essentially works like a message queue that gets processed as limits allow. The clients are blind to this and can keep sending their requests as before.

### Enable connection pooling

1. Copy and paste the connection string from earlier to `DIRECT_URL`

```sh .env (excerpt)
...
DIRECT_URL=postgresql://postgres:<PASSWORD>@db.<ID>.supabase.co:5432/postgres?schema=triggerdotdev
...
```

2. Navigate to `Project Settings -> Database` and copy your connection pool URL

<Frame>
<img src="/images/supabase-pool-url.png" alt="Supabase - Connection Pool URL" />
</Frame>

3. Paste it into your `.env` file next to `DATABASE_URL`

4. Append `?schema=triggerdotdev&pgbouncer=true` and insert your password

```sh .env (excerpt)
...
# notice the differing ports and additional query param
DATABASE_URL=postgresql://postgres:<PASSWORD>@db.<ID>.supabase.co:6543/postgres?schema=triggerdotdev&pgbouncer=true
DIRECT_URL=postgresql://postgres:<PASSWORD>@db.<ID>.supabase.co:5432/postgres?schema=triggerdotdev
...
```

5. All done! You can now enjoy the benefits of connection pooling ⚡️

## Next steps

Expand Down
8 changes: 8 additions & 0 deletions docs/documentation/guides/tunneling-platform.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ There are a few ways to do this, but we recommend using [ngrok](https://ngrok.co
brew install ngrok/ngrok/ngrok
```

```sh Linux
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
sudo tee /etc/apt/sources.list.d/ngrok.list && \
sudo apt update && sudo apt install ngrok
```

```sh Windows
choco install ngrok
```
Expand Down
Binary file added docs/images/supabase-pool-url.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/database/.env
1 change: 0 additions & 1 deletion packages/database/.env.example

This file was deleted.

4 changes: 2 additions & 2 deletions packages/database/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
node_modules
# Keep environment variables out of version control
.env
# Ensure the .env symlink is not removed by accident
!.env
5 changes: 3 additions & 2 deletions packages/database/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL")
}

generator client {
Expand Down
1 change: 1 addition & 0 deletions tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const setDB = async (cb: SetDBCallback) => {
datasources: {
db: {
url: DATABASE_URL,
// We can't set directUrl here, and we don't have to
},
},
});
Expand Down
1 change: 1 addition & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"REMIX_APP_PORT",
"CI",
"DATABASE_URL",
"DIRECT_URL",
"SESSION_SECRET",
"APP_ORIGIN",
"LOGIN_ORIGIN",
Expand Down

0 comments on commit 603ffbc

Please sign in to comment.