Ein Supabase-Backend betreiben
Este conteúdo não está disponível em sua língua ainda.
Eine Instanz mit RLS_DEFAULT_CONNECTOR=supabase liest und schreibt in eine Postgres-Datenbank hinter Supabase. Den Stack dafür gibt es im Repo unter deploy/supabase/. Die Daten liegen dort im Klartext beim Betreiber. Wer welche Zeile lesen und schreiben darf, entscheiden Row-Level-Security-Policies in der Datenbank, nicht die App.
Was im Stack ist
| Dienst | Aufgabe |
|---|---|
db |
Postgres 17 mit den Supabase-Erweiterungen |
auth |
GoTrue: Konten, Anmeldung, JWTs |
rest |
PostgREST: Lesen und Schreiben über HTTP |
realtime |
Änderungen live an die App (postgres_changes) |
kong |
das eine Tor nach außen, prüft den apikey |
Studio, Analytics und Storage sind nicht dabei. Die Versionen sind gepinnt; ein automatisches Update gibt es bewusst nicht, weil ein Postgres-Major-Wechsel ohne Migration Daten verliert.
Aufsetzen
Ihr braucht Docker mit Compose-Plugin, einen laufenden Traefik-Container namens traefik mit dem EntryPoint websecure und dem Resolver letsencrypt, und einen DNS-Eintrag für die API-Domain.
# vom Repo-Root auf den Serverscp -r deploy/supabase user@server:apps/scp -r supabase/migrations user@server:apps/supabase/
# auf dem Servercd apps/supabaseSUPABASE_DOMAIN=supabase.example.org \SITE_URL=https://netzwerk.example.org \./generate-secrets.shdocker compose up -d./apply-migrations.sh./smoke.shgenerate-secrets.sh schreibt eine .env mit frischen Schlüsseln (Rechte 600), verbindet Traefik mit dem Netz supabase und gibt nur den ANON_KEY aus. Dieser Schlüssel ist öffentlich, er steht in jedem Browser. SERVICE_ROLE_KEY und JWT_SECRET umgehen jede Policy und verlassen den Server nie.
apply-migrations.sh spielt das Schema aus supabase/migrations/ ein und merkt sich, was schon angewendet ist. smoke.sh prüft die Grenze durch Kong: Ein Eintrag mit eigenem Autor geht durch, einer mit fremdem Autor scheitert.
Die App anschließen
In der .env der Instanz:
RLS_DEFAULT_CONNECTOR=supabaseRLS_SUPABASE_URL=https://supabase.example.orgRLS_SUPABASE_ANON_KEY=<ANON_KEY aus generate-secrets.sh>Dann docker compose up -d in der Instanz. Die App zeigt den Anmeldebildschirm des Toolkits.
Anmeldung
Der Connector Die Implementierung des DataInterface für eine konkrete Datenquelle, ergänzt um unterstützte Capabilities. Die Steckstelle des Stacks nach unten. GlossarConnector The implementation of the DataInterface for one data source, plus the capabilities it supports. The stack's socket downward. Glossary bietet drei Wege: E-Mail mit Passwort, Registrierung mit E-Mail und Passwort, und ein anonymes Konto zum Ausprobieren. Ohne SMTP bestätigt GoTrue jede Registrierung sofort, die E-Mail-Adresse ist also nicht geprüft, und ein Passwort-Reset per Mail geht nicht. Wer das braucht, setzt in docker-compose.yml die GOTRUE_SMTP_*-Variablen und GOTRUE_MAILER_AUTOCONFIRM: "false". Die Links in den Mails zeigen schon auf /auth/v1/verify, den Pfad, den Kong an GoTrue durchreicht. Wer keine anonymen Konten will, setzt GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: "false".
Ein Konto ist hier eine Supabase-UUID, keine DID. Wie die Anmeldung über Connectoren hinweg gebaut ist, steht unter Identität und Anmeldung.
Wer was sieht
- Items ohne Space Der gemeinsame Arbeits-, Mitgliedschafts- und Sichtbarkeitskontext. Im Datenvertrag heißt er Group. GlossarSpace The shared context for work, membership and visibility. In the data contract it is called Group. Glossary sieht jeder angemeldete Nutzer der Instanz.
- Items in einem Space lesen und schreiben nur dessen Mitglied Vorgeschlagen: wer zu einem Space gehört. Die Anwendungsschicht liest Mitgliedschaft über den Connector und konstruiert sie nicht selbst; wie sie gespeichert und belegt wird, entscheidet der jeweilige Connector (der lokale Connector hält sie in groupMembers, der RLTP-Connector leitet sie aus Gruppen-Log und Schlüssel ab). GlossarMember Proposed: who belongs to a space. The application layer reads membership through the connector and does not construct it; how it is stored and proven is decided by the connector in use (the local connector keeps it in groupMembers, the RLTP connector derives it from the group log and key). Glossary. Relation Eine gerichtete Beziehung zwischen Items mit Prädikat und Ziel. Rückverweise zeigen sie aus der Gegenrichtung. GlossarRelation A directed link between items with predicate and target. Back-references show it from the opposite direction. Glossary, Kommentare und Reaktionen ändert und löscht nur, wer sie geschrieben hat.
- Spaces und Mitgliederlisten sehen nur Ersteller und Mitglieder. Einladen dürfen nur Mitglieder.
- Personenprofil Die fachliche Darstellung einer Person als Item nach Profilvertrag. Die User-Identität ist ein eigener Begriff. GlossarPerson profile The domain representation of a person as an item under the profile contract. The user identity is a separate term. Glossary sind für alle Angemeldeten lesbar, damit man beim Einladen jemanden findet.
- Kontakte sieht nur, wer an der Kante beteiligt ist.
- Ohne Anmeldung liefert die Datenbank nichts.
Der Autor eines Eintrags kommt aus der Sitzung (auth.uid()), nie aus den gesendeten Daten. Ein Eintrag wechselt seinen Space nicht, und das Löschen eines Space löscht seine Inhalte mit.
Prüfen
Die Live-Contract-Suite fährt dieselben Vertragstests wie für jeden Connector, dazu Grenztests für die Policies. Sie legt Konten an und lässt Einträge zurück, die angemeldete Nutzer sehen. Fahrt sie deshalb gegen eine eigene Testinstanz, nicht gegen eine, die Menschen benutzen. Holt ANON_KEY und SERVICE_ROLE_KEY aus der .env der Testinstanz in die Shell, dann:
SUPABASE_URL=https://supabase-test.example.org \SUPABASE_ANON_KEY="$ANON_KEY" \SUPABASE_SERVICE_ROLE_KEY="$SERVICE_ROLE_KEY" \pnpm --filter @real-life/supabase-connector testDen SERVICE_ROLE_KEY braucht die Suite, um Testdaten fremder Autoren anzulegen. Lasst sie von einem vertrauenswürdigen Rechner laufen.
Pflegen und sichern
Neue Migrationen kommen mit neuen Versionen des Stacks in supabase/migrations/. Kopiert sie auf den Server und ruft ./apply-migrations.sh erneut auf. Neuere Images tragt ihr von Hand in docker-compose.yml ein, nach einem Backup.
Der Stack sichert nichts von selbst. Ein logisches Backup mit Inhalten und Konten:
docker exec supabase-db pg_dump -U supabase_admin -Fc postgres > rls-$(date +%F).dumpDie .env gehört dazu. Ohne dasselbe JWT_SECRET sind ausgegebene Schlüssel und Sitzungen ungültig.
Neue Schlüssel macht ihr, indem ihr die .env beiseitelegt (mv .env .env.alt) und generate-secrets.sh mit SUPABASE_DOMAIN und SITE_URL aus der alten Datei erneut aufruft. Danach sind alle Sitzungen ungültig, und die App braucht den neuen ANON_KEY.
Wenn etwas nicht funktioniert
docker compose upbricht mit „SUPABASE_DOMAIN fehlt“ ab: Die ZeileSUPABASE_DOMAIN=…in.envergänzen.- Traefik routet nicht mehr: Wurde der Traefik-Container neu erstellt, ist er nicht mehr im Netz
supabase../generate-secrets.sherneut ausführen; es überschreibt keine bestehende.env. - Kein Zertifikat nach neuem DNS-Eintrag: Traefik wiederholt eine gescheiterte ACME-Prüfung nicht von selbst.
docker restart traefik. - 401 bei einer Anfrage ohne
apikey: So soll es sein. Kong lässt nur Anfragen mit Schlüssel durch. - GoTrue startet in einer Schleife mit „must be owner of function uid“: Die Datenbank wurde ohne
db-init/97-auth-fn-owner.sqlangelegt. Volume löschen und neu aufsetzen, solange noch keine Daten darin sind.