diff --git a/internal/db/dump/dump.go b/internal/db/dump/dump.go index a52b1dc41c..94e2ba7afc 100644 --- a/internal/db/dump/dump.go +++ b/internal/db/dump/dump.go @@ -100,6 +100,7 @@ func dumpData(ctx context.Context, config pgconn.Config, schema, excludeTable [] // "storage", // "supabase_functions", "supabase_migrations", + // TODO: Remove in a few version in favor of _supabase internal db "_analytics", "_realtime", "_supavisor", diff --git a/internal/db/reset/reset.go b/internal/db/reset/reset.go index 62c3d33503..d53392ae92 100644 --- a/internal/db/reset/reset.go +++ b/internal/db/reset/reset.go @@ -171,6 +171,8 @@ func recreateDatabase(ctx context.Context, options ...func(*pgx.ConnConfig)) err Statements: []string{ "DROP DATABASE IF EXISTS postgres WITH (FORCE)", "CREATE DATABASE postgres WITH OWNER postgres", + "DROP DATABASE IF EXISTS _supabase WITH (FORCE)", + "CREATE DATABASE _supabase WITH OWNER postgres", }, } return sql.ExecBatch(ctx, conn) diff --git a/internal/db/reset/reset_test.go b/internal/db/reset/reset_test.go index 0be21f3b27..ace03c9b41 100644 --- a/internal/db/reset/reset_test.go +++ b/internal/db/reset/reset_test.go @@ -145,6 +145,10 @@ func TestRecreateDatabase(t *testing.T) { Query("DROP DATABASE IF EXISTS postgres WITH (FORCE)"). Reply("DROP DATABASE"). Query("CREATE DATABASE postgres WITH OWNER postgres"). + Reply("CREATE DATABASE"). + Query("DROP DATABASE IF EXISTS _supabase WITH (FORCE)"). + Reply("DROP DATABASE"). + Query("CREATE DATABASE _supabase WITH OWNER postgres"). Reply("CREATE DATABASE") // Run test assert.NoError(t, recreateDatabase(context.Background(), conn.Intercept)) @@ -194,8 +198,11 @@ func TestRecreateDatabase(t *testing.T) { Reply("DO"). Query("DROP DATABASE IF EXISTS postgres WITH (FORCE)"). ReplyError(pgerrcode.ObjectInUse, `database "postgres" is used by an active logical replication slot`). - Query("CREATE DATABASE postgres WITH OWNER postgres") - // Run test + Query("CREATE DATABASE postgres WITH OWNER postgres"). + Query("DROP DATABASE IF EXISTS _supabase WITH (FORCE)"). + Reply("DROP DATABASE"). + Query("CREATE DATABASE _supabase WITH OWNER postgres"). + Reply("CREATE DATABASE") err := recreateDatabase(context.Background(), conn.Intercept) // Check error assert.ErrorContains(t, err, `ERROR: database "postgres" is used by an active logical replication slot (SQLSTATE 55006)`) diff --git a/internal/db/start/start.go b/internal/db/start/start.go index 3039b04d96..74e40554a3 100644 --- a/internal/db/start/start.go +++ b/internal/db/start/start.go @@ -29,6 +29,8 @@ var ( HealthTimeout = 120 * time.Second //go:embed templates/schema.sql initialSchema string + //go:embed templates/_supabase.sql + _supabaseSchema string ) func Run(ctx context.Context, fsys afero.Fs) error { @@ -83,6 +85,7 @@ func NewContainerConfig() container.Config { }, Entrypoint: []string{"sh", "-c", `cat <<'EOF' > /etc/postgresql.schema.sql && cat <<'EOF' > /etc/postgresql-custom/pgsodium_root.key && docker-entrypoint.sh postgres -D /etc/postgresql ` + initialSchema + ` +` + _supabaseSchema + ` EOF ` + utils.Config.Db.RootKey + ` EOF @@ -122,7 +125,12 @@ func StartDatabase(ctx context.Context, fsys afero.Fs, w io.Writer, options ...f }, } if utils.Config.Db.MajorVersion <= 14 { - config.Entrypoint = nil + config.Entrypoint = []string{"sh", "-c", ` + cat <<'EOF' > /docker-entrypoint-initdb.d/supabase_schema.sql +` + _supabaseSchema + ` +EOF + docker-entrypoint.sh postgres -D /etc/postgresql + `} hostConfig.Tmpfs = map[string]string{"/docker-entrypoint-initdb.d": ""} } // Creating volume will not override existing volume, so we must inspect explicitly diff --git a/internal/db/start/templates/_supabase.sql b/internal/db/start/templates/_supabase.sql new file mode 100644 index 0000000000..6e5d8487ba --- /dev/null +++ b/internal/db/start/templates/_supabase.sql @@ -0,0 +1,13 @@ +CREATE DATABASE _supabase WITH OWNER postgres; + +-- Switch to the newly created _supabase database +\c _supabase +-- Create schemas in _supabase database for +-- internals tools and reports to not overload user database +-- with non-user activity +CREATE SCHEMA IF NOT EXISTS _analytics; +ALTER SCHEMA _analytics OWNER TO postgres; + +CREATE SCHEMA IF NOT EXISTS _supavisor; +ALTER SCHEMA _supavisor OWNER TO postgres; +\c postgres diff --git a/internal/db/start/templates/schema.sql b/internal/db/start/templates/schema.sql index 0d00102316..534dd12073 100644 --- a/internal/db/start/templates/schema.sql +++ b/internal/db/start/templates/schema.sql @@ -15,12 +15,6 @@ ALTER USER supabase_read_only_user WITH PASSWORD :'pgpass'; create schema if not exists _realtime; alter schema _realtime owner to postgres; -create schema if not exists _analytics; -alter schema _analytics owner to postgres; - -create schema if not exists _supavisor; -alter schema _supavisor owner to postgres; - BEGIN; -- Create pg_net extension diff --git a/internal/start/start.go b/internal/start/start.go index 2c3017ce5e..72f34b8e71 100644 --- a/internal/start/start.go +++ b/internal/start/start.go @@ -195,7 +195,7 @@ func run(p utils.Program, ctx context.Context, fsys afero.Fs, excludedContainers // Start Logflare if utils.Config.Analytics.Enabled && !isContainerExcluded(utils.Config.Analytics.Image, excluded) { env := []string{ - "DB_DATABASE=" + dbConfig.Database, + "DB_DATABASE=_supabase", "DB_HOSTNAME=" + dbConfig.Host, fmt.Sprintf("DB_PORT=%d", dbConfig.Port), "DB_SCHEMA=_analytics", @@ -228,7 +228,7 @@ func run(p utils.Program, ctx context.Context, fsys afero.Fs, excludedContainers ) case config.LogflarePostgres: env = append(env, - fmt.Sprintf("POSTGRES_BACKEND_URL=postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database), + fmt.Sprintf("POSTGRES_BACKEND_URL=postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"), "POSTGRES_BACKEND_SCHEMA=_analytics", ) } @@ -1045,7 +1045,7 @@ EOF "PORT=4000", fmt.Sprintf("PROXY_PORT_SESSION=%d", portSession), fmt.Sprintf("PROXY_PORT_TRANSACTION=%d", portTransaction), - fmt.Sprintf("DATABASE_URL=ecto://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database), + fmt.Sprintf("DATABASE_URL=ecto://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"), "CLUSTER_POSTGRES=true", "SECRET_KEY_BASE=" + utils.Config.Db.Pooler.SecretKeyBase, "VAULT_ENC_KEY=" + utils.Config.Db.Pooler.EncryptionKey,