This repository has been archived on 2026-05-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tippspiel/docs/SUPABASE_MIGRATION.md
Ronny fde9d7799c
Build & Deploy Tippspiel / build (push) Successful in 40s
docs: add Supabase credential migration guide
Documents the JWT-to-sb_secret key migration, deployment touchpoints
(local .env, Portainer Stack 115, Gitea workflow), and the fresh-clone
.env setup needed after machine migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 00:42:38 +02:00

5.1 KiB

Supabase Credential Migration — Deployment Notes

Hintergrund

Das Tippspiel-Repo hatte versehentlich Secrets im Git-History (alter .gitea/workflows/build.yml). Im Zuge der Bereinigung wurden:

  • DB-Passwort rotiert
  • Service Role Key vom Legacy-JWT-Format auf das neue Supabase-Schlüsselformat migriert

Die alten Werte sind ungültig — Deployments mit alter Konfiguration funktionieren nicht mehr.

Supabase Key-System: was sich geändert hat

Supabase hat das API-Key-System umgestellt:

Alt (Legacy, JWT) Neu
anon (Browser/Public) sb_publishable_...
service_role (Backend) sb_secret_...

Wichtige Unterschiede:

  • Legacy-Keys sind JWTs (lange Strings beginnend mit eyJ...), neue Keys sind Tokens beginnend mit sb_secret_... bzw. sb_publishable_...
  • Legacy-Keys können nur als Gruppe rotiert werden (per JWT-Secret-Reset, invalidiert alle User-Sessions)
  • Neue Keys sind einzeln rotierbar
  • Das Supabase-SDK akzeptiert beide Formate — kein Code-Change nötig, nur die Env-Variable austauschen

Wir nutzen jetzt den neuen sb_secret_...-Key unter dem Variablennamen SUPABASE_SERVICE_ROLE_KEY.

Betroffene Variablen

Variable Wo zu finden
DATABASE_URL Supabase Dashboard → Project Settings → Database → Connection string (Transaction Pooler, Port 6543)
SUPABASE_URL Supabase Dashboard → Project Settings → API (unverändert)
SUPABASE_SERVICE_ROLE_KEY Supabase Dashboard → Project Settings → API Keys → Secret keys Tab → sb_secret_...

Wichtig: Bei DATABASE_URL den Transaction Pooler (Port 6543, Host aws-0-eu-west-1.pooler.supabase.com, User postgres.<project-ref>) verwenden — nicht Direct Connection (Port 5432, Host db.<project-ref>.supabase.co). Direct Connection läuft nur über IPv6 und scheitert in vielen Umgebungen mit ENOTFOUND.

Korrektes URL-Format (Pooler):

postgresql://postgres.<project-ref>:<password>@aws-0-eu-west-1.pooler.supabase.com:6543/postgres

Deployment-Stellen

Die Variablen müssen an drei Stellen synchron gehalten werden:

1. Lokales Dev-Environment

Datei: backend/.env (gitignored, nicht im Repo).

Wichtig bei frischem Clone / Maschinenwechsel: backend/.env ist bewusst nicht in Git — Secrets gehören niemals ins Repo. Stattdessen liegt backend/.env.example als Template mit Platzhaltern bei. Auf jeder neuen Maschine einmalig:

cd backend
cp .env.example .env
# dann .env öffnen und Platzhalter durch echte Werte ersetzen

Mindestens benötigte Werte für lauffähiges Dev-Setup:

DATABASE_URL=postgresql://postgres.<project-ref>:<password>@aws-0-eu-west-1.pooler.supabase.com:6543/postgres
SUPABASE_URL=https://<project-ref>.supabase.co
SUPABASE_SERVICE_ROLE_KEY=sb_secret_...
FOOTBALL_API_KEY=...

ANTHROPIC_API_KEY und ELEVENLABS_API_KEY aus .env.example werden aktuell nicht benötigt (Features wurden entfernt).

Empfehlung: Werte in einem Passwort-Manager (1Password, Bitwarden o.ä.) hinterlegen, damit sie beim nächsten Umzug sofort zur Hand sind. Niemals per E-Mail/Slack/Chat verschicken.

2. Portainer Stack wm2026-tippspiel (Stack 115)

Portainer UI → Stack → Environment variables → Werte ersetzen → Update the stack

Häufiger Fehler: Beim Pasten nicht den Variablennamen mitkopieren. Ins Value-Feld kommt nur der reine Wert, nicht DATABASE_URL=postgresql://.... Sonst entsteht eine doppelte Präfix-Verschachtelung und der Container kann keine DB-Verbindung aufbauen.

3. CI/CD Workflow (.gitea/workflows/build.yml)

Der Workflow holt die Env-Vars dynamisch aus der Portainer Stack-Konfig (Schritt 2). Im Repo selbst stehen keine Secrets, sondern nur Referenzen wie ${{ secrets.PORTAINER_TOKEN }} und ${{ secrets.DEPLOY_TOKEN }}. Diese beiden Gitea-Secrets bleiben unverändert.

Migration-Checklist für neue Umgebung

  • Aktuelles DB-Passwort aus Supabase abrufen (oder neu setzen unter Project Settings → Database)
  • Aktuellen sb_secret_...-Key aus Supabase Dashboard kopieren (API Keys → Secret keys)
  • Connection String aus Pooler-Tab kopieren, [YOUR-PASSWORD] ersetzen
  • In Ziel-Stack die drei Variablen setzen: DATABASE_URL, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY
  • Stack redeployen
  • Smoke-Test: curl http://<host>:<port>/api/matches → soll JSON mit matches-Array liefern (kein 500)
  • Falls 500: Container-Logs prüfen auf ENOTFOUND (→ Direct Connection statt Pooler) oder 28P01 invalid_password (→ Passwort falsch oder Pooler-Cache braucht ~30s)

Code-relevante Stellen

  • DB-Pool wird konfiguriert in backend/src/db/client.ts — liest DATABASE_URL
  • SSL ist nur in NODE_ENV=production aktiv, mit rejectUnauthorized: false
  • Pool-Settings: max 10 Verbindungen, 5s Connection-Timeout, 30s Idle-Timeout

Referenzen