Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add supavisor to supabase #2712

Open
wants to merge 6 commits into
base: next
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion templates/compose/supabase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,13 @@ services:
ALTER USER supabase_auth_admin WITH PASSWORD :'pgpass';
ALTER USER supabase_functions_admin WITH PASSWORD :'pgpass';
ALTER USER supabase_storage_admin WITH PASSWORD :'pgpass';
- type: bind
source: ./volumes/db/supavisor.sql
target: /docker-entrypoint-initdb.d/init-scripts/99-supavisor.sql
content: |
\set pguser `echo "supabase_admin"`

create schema if not exists _supavisor;
- type: bind
source: ./volumes/db/jwt.sql
target: /docker-entrypoint-initdb.d/init-scripts/99-jwt.sql
Expand All @@ -597,6 +604,90 @@ services:
# Use named volume to persist pgsodium decryption key between restarts
- supabase-db-config:/etc/postgresql-custom

supabase-supavisor-setup:
image: curlimages/curl:8.8.0
restart: "no"
depends_on:
supabase-supavisor:
condition: service_healthy
environment:
- SETUP_SERVICE_SUPABASEANON_KEY=${SERVICE_SUPABASEANON_KEY}
- SETUP_POSTGRES_HOST=${POSTGRES_HOST:-supabase-db}
- SETUP_POSTGRES_PORT=${POSTGRES_PORT:-5432}
- SETUP_POSTGRES_DB=${POSTGRES_DB:-postgres}
- SETUP_SERVICE_PASSWORD_POSTGRES=${SERVICE_PASSWORD_POSTGRES}
entrypoint: [ "sh", "-c" ]
command: >
#!/bin/sh

while ! curl -sSfL --head -o /dev/null -H "Authorization: Bearer $SETUP_SERVICE_SUPABASEANON_KEY" http://supabase-supavisor:4000/api/health; do
sleep 2;
done;

curl -X PUT 'http://supabase-supavisor:4000/api/tenants/dev_tenant' \
--header 'Accept: */*' \
--header 'User-Agent: Thunder Client (https://www.thunderclient.com)' \
--header 'Authorization: Bearer $SETUP_SERVICE_SUPABASEANON_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"tenant": {
"db_host": "${SETUP_POSTGRES_HOST}",
"db_port": ${SETUP_POSTGRES_PORT},
"db_database": "${SETUP_POSTGRES_DB}",
"ip_version": "auto",
"enforce_ssl": false,
"require_user": false,
"auth_query": "SELECT rolname, rolpassword FROM pg_authid WHERE rolname=$1;",
"users": [
{
"db_user": "postgres",
"db_password": "${SETUP_SERVICE_PASSWORD_POSTGRES}",
"pool_size": 20,
"mode_type": "transaction",
"is_manager": true
}
]
}
}'
exit 0


supabase-supavisor:
image: supabase/supavisor:1.1.67
healthcheck:
test:
[
"CMD",
"curl",
"-sSfL",
"--head",
"-o",
"/dev/null",
"-H",
"Authorization: Bearer ${SERVICE_SUPABASEANON_KEY}",
"http://127.0.0.1:4000/api/health",
]
timeout: 5s
interval: 5s
retries: 3
environment:
- PORT=4000
- PROXY_PORT_SESSION=5452
- PROXY_PORT_TRANSACTION=6543
- DATABASE_URL=ecto://postgres:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOST:-supabase-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres}
- CLUSTER_POSTGRES=true
- SECRET_KEY_BASE=12345678901234567890121234567890123456789012345678903212345678901234567890123456789032123456789012345678901234567890323456789032

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These probably shouldn't be hard coded

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you recommend? They need to specifically be this length

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally there's a way to generate a random string either through docker-compose or coolify, I couldn't find one though.

Considering this should be unique to every user, and I don't imagine many people are changing the defaults while using these, I'd either wait for the functionality to be added into coolify, or force the user to enter the information.

You can get docker-compose to error if an environment variable is missing using ${VAR:?error} so that would mean changing it to: SECRET_KEY_BASE=${SECRET_KEY_BASE:?error}.

Supabase is a fairly popular template, so people would need to be told that they need to put in a variable that contains a string that is X character long, but I don't know where a good place for the instruction to go would be.

Failing all that, maybe setting it to SECRET_KEY_BASE=${SECRET_KEY_BASE} and finding where the default values for Dashboard User and Dashboard Password are generated and ensure a new one is generated for the 2 variables that need them.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appears there is some functionality to do this:

case 'PASSWORD':
$generatedValue = Str::password(symbols: false);
break;
case 'PASSWORD_64':
$generatedValue = Str::password(length: 64, symbols: false);
break;
// This is not base64, it's just a random string
case 'BASE64_64':
$generatedValue = Str::random(64);
break;
case 'BASE64_128':
$generatedValue = Str::random(128);
break;
case 'BASE64':
case 'BASE64_32':
$generatedValue = Str::random(32);
break;
// This is base64,
case 'REALBASE64_64':
$generatedValue = base64_encode(Str::random(64));
break;
case 'REALBASE64_128':
$generatedValue = base64_encode(Str::random(128));
break;
case 'REALBASE64':
case 'REALBASE64_32':
$generatedValue = base64_encode(Str::random(32));
break;
case 'USER':
$generatedValue = Str::random(16);
break;
case 'SUPABASEANON':
$signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first();
if (is_null($signingKey)) {
return;
} else {
$signingKey = $signingKey->value;
}
$key = InMemory::plainText($signingKey);
$algorithm = new Sha256();
$tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default()));
$now = new DateTimeImmutable();
$now = $now->setTime($now->format('H'), $now->format('i'));
$token = $tokenBuilder
->issuedBy('supabase')
->issuedAt($now)
->expiresAt($now->modify('+100 year'))
->withClaim('role', 'anon')
->getToken($algorithm, $key);
$generatedValue = $token->toString();
break;
case 'SUPABASESERVICE':
$signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first();
if (is_null($signingKey)) {
return;
} else {
$signingKey = $signingKey->value;
}
$key = InMemory::plainText($signingKey);
$algorithm = new Sha256();
$tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default()));
$now = new DateTimeImmutable();
$now = $now->setTime($now->format('H'), $now->format('i'));
$token = $tokenBuilder
->issuedBy('supabase')
->issuedAt($now)
->expiresAt($now->modify('+100 year'))
->withClaim('role', 'service_role')
->getToken($algorithm, $key);
$generatedValue = $token->toString();
break;
default:
$generatedValue = Str::random(16);
break;
}
return $generatedValue;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this will work.

- SECRET_KEY_BASE=${SERVICE_BASE64_128_SUPAVISOR}
- VAULT_ENC_KEY=${SERVICE_PASSWORD_64_SUPAVISOR}

Doesn't actually need to be 128 characters I don't think, fly deployment docs suggest some secure value: https://supabase.github.io/supavisor/deployment/fly/

Might be worth setting them both to PASSWORD_64 if only for better naming.

- VAULT_ENC_KEY=12345678901234567890123456789032
- API_JWT_SECRET=${SERVICE_PASSWORD_JWT}
- METRICS_JWT_SECRET=${SERVICE_PASSWORD_JWT}
- REGION=local
- ERL_AFLAGS=-proto_dist inet_tcp
depends_on:
supabase-db:
condition: service_healthy
restart: unless-stopped
command: sh -c "/app/bin/migrate && /app/bin/server"

supabase-analytics:
image: supabase/logflare:1.4.0
healthcheck:
Expand Down Expand Up @@ -1013,7 +1104,7 @@ services:
"/dev/null",
"-H",
"Authorization: Bearer ${SERVICE_SUPABASEANON_KEY}",
"http://127.0.0.1:4000/api/tenants/realtime-dev/health"
"http://127.0.0.1:4000/api/tenants/realtime-dev/health",
]
timeout: 5s
interval: 5s
Expand Down