feat: introduce _supabase database add supavisor to self-hosted (#29596)
* chore: move _analytics to a distinct database Following: https://github.com/supabase/cli/pull/2707 BREAKING CHANGES: When migrating from an older version you will need to manually create the new internal _supabase database and analytics schema the same way the and do. Via: * feat: add supavisor to the self-hosted stack * chore(docs): add docs about supavisor * chore: fix reviewdog warning * chore: fix typo * chore: apply pr comments
This commit is contained in:
@@ -240,6 +240,7 @@ If the tool doesn't exist, we build and open source it ourselves.
|
||||
- [Storage](https://github.com/supabase/storage-api) provides a RESTful interface for managing Files stored in S3, using Postgres to manage permissions.
|
||||
- [postgres-meta](https://github.com/supabase/postgres-meta) is a RESTful API for managing your Postgres, allowing you to fetch tables, add roles, and run queries, etc.
|
||||
- [PostgreSQL](https://www.postgresql.org/) is an object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance.
|
||||
- [Supavisor](https://github.com/supabase/supavisor) is a scalable connection pooler for Postgres, allowing for efficient management of database connections.
|
||||
|
||||
For the system to work cohesively, some services require additional configuration within the Postgres database. For example, the APIs and Auth system require several [default roles](/docs/guides/database/postgres/roles) and the `pgjwt` Postgres extension.
|
||||
|
||||
@@ -255,6 +256,7 @@ Each system has a number of configuration options which can be found in the rele
|
||||
- [GoTrue](https://github.com/supabase/gotrue)
|
||||
- [Storage](https://github.com/supabase/storage-api)
|
||||
- [Kong](https://docs.konghq.com/gateway/latest/install/docker/)
|
||||
- [Supavisor](https://supabase.github.io/supavisor/development/docs/)
|
||||
|
||||
These configuration items are generally added to the `env` section of each service, inside the `docker-compose.yml` section. If these configuration items are sensitive, they should be stored in a [secret manager](/docs/guides/self-hosting#managing-your-secrets) or using an `.env` file and then referenced using the `${}` syntax.
|
||||
|
||||
@@ -313,11 +315,21 @@ You can find all the available options in the [storage repository](https://githu
|
||||
|
||||
By default, `docker compose` sets the database's `log_min_messages` configuration to `fatal` to prevent redundant logs generated by Realtime. You can configure `log_min_messages` using any of the Postgres [Severity Levels](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS).
|
||||
|
||||
#### Accessing Postgres through Supavisor
|
||||
|
||||
By default, the Postgres database is accessible through the Supavisor connection pooler. This allows for more efficient management of database connections. You can connect to the pooled database using the `POOLER_PROXY_PORT_TRANSACTION` port and `POSTGRES_PORT` for session based connections.
|
||||
|
||||
For more information on configuring and using Supavisor, see the [Supavisor documentation](https://supabase.github.io/supavisor/).
|
||||
|
||||
#### Exposing your Postgres database
|
||||
|
||||
By default, the Postgres database is only accessible locally. If you want to expose it to the outside world, you can update the `docker-compose.yml` file and remove the `127.0.0.1:` prefix from the `ports` section:
|
||||
If you need direct access to the Postgres database without going through Supavisor, you can expose it by updating the `docker-compose.yml` file:
|
||||
|
||||
```yaml docker-compose.yml
|
||||
# Comment or remove the supavisor section of the docker-compose file
|
||||
# supavisor:
|
||||
# ports:
|
||||
# ...
|
||||
db:
|
||||
ports:
|
||||
- ${POSTGRES_PORT}:${POSTGRES_PORT}
|
||||
|
||||
@@ -19,6 +19,14 @@ POSTGRES_DB=postgres
|
||||
POSTGRES_PORT=5432
|
||||
# default user is postgres
|
||||
|
||||
############
|
||||
# Supavisor -- Database pooler
|
||||
############
|
||||
POOLER_PROXY_PORT_TRANSACTION=6543
|
||||
POOLER_DEFAULT_POOL_SIZE=20
|
||||
POOLER_MAX_CLIENT_CONN=100
|
||||
|
||||
|
||||
############
|
||||
# API Proxy - Configuration for the Kong Reverse proxy.
|
||||
############
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans
|
||||
|
||||
name: supabase
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
studio:
|
||||
@@ -344,7 +343,7 @@ services:
|
||||
environment:
|
||||
LOGFLARE_NODE_HOST: 127.0.0.1
|
||||
DB_USERNAME: supabase_admin
|
||||
DB_DATABASE: ${POSTGRES_DB}
|
||||
DB_DATABASE: _supabase
|
||||
DB_HOSTNAME: ${POSTGRES_HOST}
|
||||
DB_PORT: ${POSTGRES_PORT}
|
||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
@@ -355,7 +354,7 @@ services:
|
||||
LOGFLARE_MIN_CLUSTER_SIZE: 1
|
||||
|
||||
# Comment variables to use Big Query backend for analytics
|
||||
POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||
POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/_supabase
|
||||
POSTGRES_BACKEND_SCHEMA: _analytics
|
||||
LOGFLARE_FEATURE_FLAG_OVERRIDE: multibackend=true
|
||||
# Uncomment to use Big Query backend for analytics
|
||||
@@ -383,9 +382,6 @@ services:
|
||||
- -c
|
||||
- log_min_messages=fatal # prevents Realtime polling queries from appearing in logs
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
# Pass down internal port because it's set dynamically by other services
|
||||
- ${POSTGRES_PORT}:${POSTGRES_PORT}
|
||||
environment:
|
||||
POSTGRES_HOST: /var/run/postgresql
|
||||
PGPORT: ${POSTGRES_PORT}
|
||||
@@ -406,8 +402,12 @@ services:
|
||||
- ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z
|
||||
# PGDATA directory is persisted between restarts
|
||||
- ./volumes/db/data:/var/lib/postgresql/data:Z
|
||||
# Changes required for internal supabase data such as _analytics
|
||||
- ./volumes/db/_supabase.sql:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:Z
|
||||
# Changes required for Analytics support
|
||||
- ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z
|
||||
# Changes required for Pooler support
|
||||
- ./volumes/db/pooler.sql:/docker-entrypoint-initdb.d/migrations/99-pooler.sql:Z
|
||||
# Use named volume to persist pgsodium decryption key between restarts
|
||||
- db-config:/etc/postgresql-custom
|
||||
|
||||
@@ -435,5 +435,47 @@ services:
|
||||
LOGFLARE_API_KEY: ${LOGFLARE_API_KEY}
|
||||
command: [ "--config", "etc/vector/vector.yml" ]
|
||||
|
||||
# Update the DATABASE_URL if you are using an external Postgres database
|
||||
supavisor:
|
||||
container_name: supabase-pooler
|
||||
image: supabase/supavisor:1.1.56
|
||||
healthcheck:
|
||||
test: curl -sSfL --head -o /dev/null "http://127.0.0.1:4000/api/health"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
analytics:
|
||||
condition: service_healthy
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- /app/bin/migrate && /app/bin/supavisor eval "$$(cat /etc/pooler/pooler.exs)" && /app/bin/server
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- ${POSTGRES_PORT}:${POSTGRES_PORT}
|
||||
- ${POOLER_PROXY_PORT_TRANSACTION}:${POOLER_PROXY_PORT_TRANSACTION}
|
||||
environment:
|
||||
- PORT=4000
|
||||
- POSTGRES_PORT=${POSTGRES_PORT}
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- DATABASE_URL=ecto://postgres:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/_supabase
|
||||
- CLUSTER_POSTGRES=true
|
||||
- SECRET_KEY_BASE=UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq
|
||||
- VAULT_ENC_KEY=your-encryption-key-32-chars-min
|
||||
- API_JWT_SECRET=${JWT_SECRET}
|
||||
- METRICS_JWT_SECRET=${JWT_SECRET}
|
||||
- REGION=local
|
||||
- ERL_AFLAGS=-proto_dist inet_tcp
|
||||
- POOLER_TENANT_ID=your-tenant-id
|
||||
- POOLER_DEFAULT_POOL_SIZE=${POOLER_DEFAULT_POOL_SIZE}
|
||||
- POOLER_MAX_CLIENT_CONN=${POOLER_MAX_CLIENT_CONN}
|
||||
- POOLER_POOL_MODE=transaction
|
||||
volumes:
|
||||
- ./volumes/pooler/pooler.exs:/etc/pooler/pooler.exs:ro
|
||||
|
||||
volumes:
|
||||
db-config:
|
||||
|
||||
3
docker/volumes/db/_supabase.sql
Normal file
3
docker/volumes/db/_supabase.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
\set pguser `echo "$POSTGRES_USER"`
|
||||
|
||||
CREATE DATABASE _supabase WITH OWNER :pguser;
|
||||
@@ -1,4 +1,5 @@
|
||||
\set pguser `echo "$POSTGRES_USER"`
|
||||
|
||||
\c _supabase
|
||||
create schema if not exists _analytics;
|
||||
alter schema _analytics owner to :pguser;
|
||||
|
||||
5
docker/volumes/db/pooler.sql
Normal file
5
docker/volumes/db/pooler.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
\set pguser `echo "$POSTGRES_USER"`
|
||||
|
||||
\c _supabase
|
||||
create schema if not exists _supavisor;
|
||||
alter schema _supavisor owner to :pguser;
|
||||
30
docker/volumes/pooler/pooler.exs
Normal file
30
docker/volumes/pooler/pooler.exs
Normal file
@@ -0,0 +1,30 @@
|
||||
{:ok, _} = Application.ensure_all_started(:supavisor)
|
||||
|
||||
{:ok, version} =
|
||||
case Supavisor.Repo.query!("select version()") do
|
||||
%{rows: [[ver]]} -> Supavisor.Helpers.parse_pg_version(ver)
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
params = %{
|
||||
"external_id" => System.get_env("POOLER_TENANT_ID"),
|
||||
"db_host" => "db",
|
||||
"db_port" => System.get_env("POSTGRES_PORT"),
|
||||
"db_database" => System.get_env("POSTGRES_DB"),
|
||||
"require_user" => false,
|
||||
"auth_query" => "SELECT * FROM pgbouncer.get_auth($1)",
|
||||
"default_max_clients" => System.get_env("POOLER_MAX_CLIENT_CONN"),
|
||||
"default_pool_size" => System.get_env("POOLER_DEFAULT_POOL_SIZE"),
|
||||
"default_parameter_status" => %{"server_version" => version},
|
||||
"users" => [%{
|
||||
"db_user" => "pgbouncer",
|
||||
"db_password" => System.get_env("POSTGRES_PASSWORD"),
|
||||
"mode_type" => System.get_env("POOLER_POOL_MODE"),
|
||||
"pool_size" => System.get_env("POOLER_DEFAULT_POOL_SIZE"),
|
||||
"is_manager" => true
|
||||
}]
|
||||
}
|
||||
|
||||
if !Supavisor.Tenants.get_tenant_by_external_id(params["external_id"]) do
|
||||
{:ok, _} = Supavisor.Tenants.create_tenant(params)
|
||||
end
|
||||
Reference in New Issue
Block a user