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>
This commit is contained in:
+50
-24
@@ -1,40 +1,66 @@
|
||||
# Supabase compose stack
|
||||
|
||||
Vendored from the official Supabase self-hosting bundle, with two deliberate
|
||||
changes:
|
||||
Vendored from the official self-hosting bundle
|
||||
(`docker/docker-compose.yml` in supabase/supabase), with deliberate changes:
|
||||
|
||||
1. The bundled `db` service is removed. Every service that talks to Postgres
|
||||
reads `POSTGRES_HOST` / `POSTGRES_PORT` from the environment and connects to
|
||||
the external `db-host`. The systemd unit (`nix/modules/gebos-supabase.nix`)
|
||||
injects these from `/etc/gebos/secrets.env`.
|
||||
1. **No `db` service.** Every service reads `POSTGRES_HOST` / `POSTGRES_PORT`
|
||||
from the environment and connects to the external `db-host`. The systemd
|
||||
unit (`nix/modules/gebos-supabase.nix`) injects these; secrets come from
|
||||
the sops-rendered env file (see `gebos-secrets.nix`).
|
||||
|
||||
2. Studio is bound to `127.0.0.1` only. There is **no public route** to it.
|
||||
To use it from your laptop:
|
||||
2. **Only auth + rest + studio (+ kong, meta).** Realtime, storage, imgproxy,
|
||||
edge functions, supavisor and the Logflare analytics stack are not
|
||||
vendored — re-add from upstream when actually needed.
|
||||
|
||||
3. **Studio is bound to `127.0.0.1` only, with no Kong dashboard route.**
|
||||
Upstream protects Studio with Kong basic-auth on a catch-all `/` route; we
|
||||
drop that route entirely (`kong.yml` here), so there is **no public route**
|
||||
to Studio and the api.gebos.online surface is only `/auth/v1`, `/rest/v1`,
|
||||
`/graphql/v1` and the two `.well-known` endpoints. To use Studio:
|
||||
|
||||
```
|
||||
ssh -L 3000:127.0.0.1:3000 app-host
|
||||
ssh -L 3000:127.0.0.1:3000 deploy@app.gebos.online
|
||||
open http://localhost:3000
|
||||
```
|
||||
|
||||
This is intentional — Studio runs with the `service_role` JWT and bypasses
|
||||
RLS. Putting it on the public internet behind only HTTP basic auth (the
|
||||
default) is too thin.
|
||||
Studio itself has no login in this topology — possession of the SSH key is
|
||||
the credential. (`supabase_dashboard_password` in secrets.yaml is currently
|
||||
unused; it becomes relevant only if Studio ever gets fronted by basic
|
||||
auth again.)
|
||||
|
||||
4. **meta connects as `supabase_admin`, not `postgres`.** In the upstream
|
||||
image `postgres`/`supabase_admin` is the superuser; on db-host the
|
||||
`postgres` superuser keeps its own password (`postgres_admin_password`),
|
||||
and the `gebos-postgres-passwords` oneshot makes `supabase_admin`
|
||||
SUPERUSER with the shared `POSTGRES_PASSWORD` to match upstream semantics.
|
||||
|
||||
## What's in here
|
||||
|
||||
- `docker-compose.yml` — the stack itself
|
||||
- `init.sql` — schemas, roles, and extensions Postgres needs before the
|
||||
compose services come up. Loaded by `nix/modules/gebos-postgres.nix`.
|
||||
- `kong.yml` — Kong's declarative routing (to be vendored alongside the compose
|
||||
file when we copy it in).
|
||||
- `init.sql` — Supabase schemas, roles, and extensions Postgres needs before
|
||||
the compose services come up. Runs once at first initdb via
|
||||
`nix/modules/gebos-postgres.nix`. Application schema lives in
|
||||
`supabase/migrations/` (applied manually — see `supabase/README.md`).
|
||||
- `kong.yml` — Kong's declarative routing, trimmed to the services we run
|
||||
- `kong-entrypoint.sh` — upstream helper, verbatim: substitutes `$VARS` into
|
||||
kong.yml (Kong has no native env interpolation) and builds the
|
||||
request-transformer Lua expressions
|
||||
|
||||
## Passwords
|
||||
|
||||
No service role has a password in any SQL file. The
|
||||
`gebos-postgres-passwords` oneshot on db-host (see `gebos-postgres.nix`)
|
||||
syncs them from sops on every boot/deploy:
|
||||
|
||||
| role | secret |
|
||||
|-----------------------------------------------------|--------|
|
||||
| `postgres` | `postgres_admin_password` |
|
||||
| `supabase_admin`, `supabase_auth_admin`, `authenticator` | `supabase_postgres_password` (= `POSTGRES_PASSWORD` in the compose env) |
|
||||
| `gebos_ingest` | `ingester_postgres_password` |
|
||||
|
||||
## Updating the vendored compose
|
||||
|
||||
When upstream Supabase ships a new compose layout, re-vendor by:
|
||||
|
||||
1. Copy upstream `docker/docker-compose.yml` over `docker-compose.yml`.
|
||||
2. Remove the `db:` service block.
|
||||
3. Replace every `db:5432` / `postgres:5432` reference with
|
||||
`${POSTGRES_HOST}:${POSTGRES_PORT}`.
|
||||
4. Bind Studio to `${STUDIO_BIND}:3000` instead of `0.0.0.0:3000`.
|
||||
5. Commit, deploy, smoke-test through the SSH tunnel.
|
||||
When upstream ships a new layout, re-vendor by copying the upstream files and
|
||||
re-applying the deviations listed at the top of `docker-compose.yml` and
|
||||
`kong.yml` (both carry the list in their header comments). Then commit,
|
||||
deploy, and smoke-test Studio through the SSH tunnel.
|
||||
|
||||
Reference in New Issue
Block a user