Files
Gebos/supabase/README.md
T
Lars Nolden 2ce68cb098
deploy / deploy (push) Successful in 5m57s
check / flake-check (push) Failing after 35m52s
Wire schema v1 into a manual Supabase migration and vendor the real stack
- Move db/schema.sql to supabase/migrations/ as the first supabase CLI
  migration (manual `db push` only, no automated runner); re-add the
  gebos_ingest role + grants there since init.sql never re-runs
- Add gebos-postgres-passwords oneshot on db-host: syncs role passwords
  from sops (LoadCredential, journal-safe), makes supabase_admin
  SUPERUSER and hands the auth schema to supabase_auth_admin to match
  the upstream supabase/postgres image; add pg_hba rule for 10.0.0.0/8
- Vendor the official docker-compose (studio/kong/auth/rest/meta only,
  external Postgres, loopback Studio with no Kong dashboard route) plus
  kong.yml (trimmed) and kong-entrypoint.sh (verbatim); tested: compose
  config, Kong config parse, migration applied on TimescaleDB pg17
- Document decisions as ADRs 0001-0004 (migrations, passwords, vendored
  stack, JWT API keys incl. verify/mint procedure)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 22:33:50 +02:00

1.9 KiB

Database migrations

Plain-SQL migrations in migrations/, applied manually with the supabase CLI (available in the dev shell). There is deliberately no automated runner: schema changes are rare, deliberate, admin-level operations.

The CLI records what has been applied in supabase_migrations.schema_migrations on the target database, so pushing is incremental and re-running it is safe.

Applying to prod (db-host)

Postgres on db-host only accepts connections from the private network, so go through an SSH tunnel:

# terminal 1 — tunnel to db-host's loopback
ssh -L 15432:127.0.0.1:5432 deploy@db.gebos.online

# terminal 2 — from the repo root, inside `nix develop`
PGPASS=$(sops -d --extract '["postgres_admin_password"]' nix/secrets/secrets.yaml)
supabase db push --db-url "postgres://postgres:${PGPASS}@127.0.0.1:15432/postgres"

The postgres superuser password is set from the same sops secret by the gebos-postgres-passwords oneshot on db-host (see nix/modules/gebos-postgres.nix), so it only works after the first deploy of that unit.

Adding a migration

supabase migration new <short_name>   # creates migrations/<timestamp>_<short_name>.sql

Write plain SQL. Conventions:

  • Migrations are ordered and applied exactly once — they do NOT need to be idempotent (the schema-v1 file's CREATE TYPEs aren't).
  • Cluster bootstrap (Supabase schemas/roles, extensions that need shared_preload_libraries) belongs in nix/supabase/init.sql, not here.
  • Role passwords never go in migrations — they are synced from sops by the gebos-postgres-passwords unit.

Local dev

nix run .#dev starts a plain Postgres via process-compose; apply migrations to it the same way:

supabase db push --db-url "postgres://gebos_ingest:dev@127.0.0.1:5432/gebos"

(Note: the dev database has no TimescaleDB unless the process-compose postgres gains the extension — create_hypertable calls will fail there until then.)