Supabase mit Docker installieren: Open-Source Firebase-Alternative selbst hosten
Supabase ist die mächtigste selbst hostbare Firebase-Alternative: PostgreSQL-Datenbank, REST-API, Auth, Realtime-Subscriptions, S3-Storage und Edge Functions – alles in einem einzigen Docker-Compose-Stack. Diese Anleitung zeigt dir den vollständigen Weg vom Git-Clone bis zum laufenden Dashboard.

Wer ein vollständiges Backend-as-a-Service-Paket selbst betreiben möchte, kommt an Supabase kaum vorbei: Mit über 104.000 GitHub-Stars (Stand 2026) vereint das Projekt eine PostgreSQL-Datenbank, eine automatisch generierte REST-API (PostgREST), Authentifizierung (GoTrue), Echtzeit-Subscriptions, S3-kompatiblen Dateispeicher, Deno-basierte Edge Functions und ein schickes Web-Dashboard – alles hinter einem Kong-API-Gateway. Die komplette Infrastruktur startet mit einem einzigen docker compose up -d. Diese Anleitung führt dich Schritt für Schritt durch die Installation auf einem beliebigen Linux-Host und erklärt dabei nicht nur das „Was", sondern vor allem das „Warum" hinter den einzelnen Konfigurationsentscheidungen.
Voraussetzungen
- Docker Engine 24+ und das Docker Compose Plugin v2 (
docker compose, nicht das veraltetedocker-compose) sind auf dem Host installiert. Falls nicht, folge der Anleitung Docker und Docker Compose auf Linux installieren. - Linux-Host (Ubuntu 22.04/24.04 empfohlen) oder eine VM – Docker Desktop auf Mac/Windows funktioniert ebenso, ist aber für Produktivbetrieb nicht empfehlenswert.
- Mindestens 4 GB RAM und 2 CPU-Kerne; empfohlen sind 8 GB RAM, 4+ Kerne und 80 GB SSD. Mit weniger als 4 GB RAM werden einzelne Container (insbesondere Realtime und Studio) regelmäßig gekillt.
- Git ist installiert (
git --version). Das Klonen des Repos ist Pflicht – ein manuelles Kopieren derdocker-compose.ymlallein reicht nicht, da Init-SQL-Skripte für den ersten Datenbankstart fehlen würden. - Port 8000 (HTTP) ist in der Firewall des Hosts freigegeben. Optional Port 8443 für HTTPS. Für Produktivbetrieb mit eigener Domain empfiehlt sich ein Reverse Proxy – mehr dazu in Schritt 6.
- Für E-Mail-Funktionen (Bestätigung, Passwort-Reset) benötigst du SMTP-Zugangsdaten, z. B. von Resend, SendGrid oder Mailgun.
Eckdaten im Überblick
| Eigenschaft | Wert |
|---|---|
| Lizenz | Apache 2.0 (Kernkomponenten), ELv2 (Studio) |
| Container-Anzahl | 11 (Studio, Kong, Auth, REST, Realtime, Storage, imgproxy, meta, Functions, PostgreSQL, Supavisor) |
| Basis-Datenbank | supabase/postgres:15.8.1.085 (modifiziertes PostgreSQL 15) |
| Externer HTTP-Port | 8000 (Kong API-Gateway) |
| Externer HTTPS-Port | 8443 (optional) |
| DB Session-Mode (Supavisor) | 5432 |
| DB Transaction-Mode (Supavisor) | 6543 |
| Dashboard-Schutz | HTTP-Basic-Auth (DASHBOARD_USERNAME / DASHBOARD_PASSWORD) |
| Mindest-RAM | 4 GB (empfohlen: 8 GB) |
| GitHub-Stars (2026) | > 104.000 |
| Service | Image (Stand Juni 2026) | Funktion |
|---|---|---|
| studio | supabase/studio:2026.06.03-sha-0bca601 | Web-Dashboard (Next.js) |
| kong | kong/kong:3.9.1 | API-Gateway (einziger ext. Eingang) |
| auth | supabase/gotrue:v2.189.0 | Authentifizierung & JWT |
| rest | postgrest/postgrest:v14.12 | Auto-REST-API |
| realtime | supabase/realtime:v2.102.3 | Echtzeit-Subscriptions (WebSocket) |
| storage | supabase/storage-api:v1.60.4 | Dateispeicher (S3-kompatibel) |
| imgproxy | darthsim/imgproxy:v3.30.1 | Bildtransformation on-the-fly |
| meta | supabase/postgres-meta:v0.96.6 | Datenbank-Verwaltungs-API |
| functions | supabase/edge-runtime:v1.74.0 | Edge Functions (Deno) |
| db | supabase/postgres:15.8.1.085 | PostgreSQL 15 mit Supabase-Extensions |
| supavisor | supabase/supavisor:2.9.5 | Connection-Pooler |
Schritt 1: Repository klonen und Projektstruktur anlegen
Das offizielle Repository enthält nicht nur die docker-compose.yml, sondern auch Init-SQL-Skripte, die beim allerersten Datenbankstart ausgeführt werden. Diese Skripte richten Rollen (anon, authenticated, service_role), PostgreSQL-Erweiterungen (pgjwt, uuid-ossp, pgcrypto) und Realtime-Tabellen ein. Ohne sie startet PostgreSQL zwar, aber alle anderen Services scheitern beim Verbindungsaufbau.
Wichtig unter Windows: Setze git config core.autocrlf false vor dem Clone, sonst werden Shell-Skripte mit CRLF-Zeilenenden ausgecheckt und Kong startet mit einem bad interpreter: ^M-Fehler.
# Nur unter Windows: CRLF-Konvertierung deaktivieren
git config --global core.autocrlf false
# Repository klonen (nur das docker/-Unterverzeichnis reicht aus)
git clone --depth=1 https://github.com/supabase/supabase
cd supabase/docker
# Verzeichnisstruktur prüfen
ls -la volumes/Du solltest jetzt das Verzeichnis supabase/docker als Arbeitsverzeichnis haben. Alle weiteren Befehle beziehen sich auf dieses Verzeichnis.
Verifizieren: Nach dem Clone muss ls volumes/ mindestens die Unterverzeichnisse api/, db/, functions/ und storage/ anzeigen. Fehlen diese, ist der Clone unvollständig.
ls volumes/
# Erwartete Ausgabe (mindestens):
# api db functions logs storageSchritt 2: Sichere Secrets generieren und .env konfigurieren
Das ist der kritischste Schritt. Die mitgelieferte .env.example enthält Demo-JWTs mit Ablauf 2029 und ein leicht erratbares Passwort – diese Werte sind öffentlich bekannt und dürfen in keiner laufenden Instanz verwendet werden. Das Repo liefert ein Hilfsskript mit, das alle benötigten Secrets automatisch erzeugt:
# Secrets generieren (erfordert openssl + node oder npx)
chmod +x utils/generate-keys.sh
sh utils/generate-keys.shDas Skript gibt dir JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY und weitere Werte aus. Kopiere diese Ausgabe. Lege danach die .env an:
cp .env.example .env
nano .env # oder dein bevorzugter EditorTrage die generierten Werte ein und passe die markierten Pflichtfelder an:
############################################################
# Supabase Self-Hosted – .env
# ALLE Secrets durch eigene Werte ersetzen!
############################################################
# --- Pflicht: Datenbank ---
POSTGRES_PASSWORD=sehr-langes-sicheres-passwort-hier # PFLICHT – nie der Defaultwert!
POSTGRES_DB=postgres
POSTGRES_HOST=db
POSTGRES_PORT=5432
# --- Pflicht: JWTs ---
# Mindestens 32 Zeichen; mit generate-keys.sh erzeugen
JWT_SECRET=mindestens-32-zeichen-langer-zufaelliger-string
ANON_KEY=eyJ... # aus generate-keys.sh – HS256-signiert mit JWT_SECRET
SERVICE_ROLE_KEY=eyJ... # aus generate-keys.sh – NIEMALS im Client verwenden!
JWT_EXPIRY=3600
# --- Pflicht: Dashboard-Zugang ---
DASHBOARD_USERNAME=supabase
# Passwort MUSS mindestens einen Buchstaben enthalten!
# Rein numerische Passwörter werden von Kong abgelehnt.
DASHBOARD_PASSWORD=MeinSicheresPasswort2026!
# --- Pflicht: URLs ---
# Ersetze durch deine echte Server-IP oder Domain (inkl. Port)
SUPABASE_PUBLIC_URL=http://192.168.1.100:8000
API_EXTERNAL_URL=http://192.168.1.100:8000
SITE_URL=http://localhost:3000
# --- Pflicht: Verschlüsselungskeys ---
SECRET_KEY_BASE=64-zeichen-zufaelliger-string-hier # für Realtime + Supavisor
VAULT_ENC_KEY=genau-32-zeichen-langer-schluessel # für Supavisor-Vault
PG_META_CRYPTO_KEY=mindestens-32-zeichen-lang # für postgres-meta
# --- Pflicht: Supavisor (Connection-Pooler) ---
POOLER_TENANT_ID=meine-tenant-id # frei wählbare eindeutige ID
POOLER_DEFAULT_POOL_SIZE=20
POOLER_MAX_CLIENT_CONN=100
POOLER_DB_POOL_SIZE=10
POOLER_PROXY_PORT_TRANSACTION=6543
# --- Kong Ports ---
KONG_HTTP_PORT=8000
KONG_HTTPS_PORT=8443
# --- Studio ---
STUDIO_DEFAULT_ORGANIZATION=Meine Organisation
STUDIO_DEFAULT_PROJECT=Mein Projekt
# --- Optional: SMTP (für E-Mail-Bestätigung) ---
SMTP_HOST=smtp.beispiel.de
SMTP_PORT=587
SMTP_USER=user@beispiel.de
SMTP_PASS=smtp-passwort
SMTP_ADMIN_EMAIL=admin@beispiel.de
SMTP_SENDER_NAME=Supabase
# --- Optional: E-Mail-Verhalten ---
ENABLE_EMAIL_SIGNUP=true
ENABLE_EMAIL_AUTOCONFIRM=false # auf true setzen für lokale Entwicklung
ENABLE_ANONYMOUS_USERS=false
DISABLE_SIGNUP=false
# --- Optional: Edge Functions ---
FUNCTIONS_VERIFY_JWT=false
# --- Optional: Auth-URLs ---
ADDITIONAL_REDIRECT_URLS=
MAILER_URLPATHS_INVITE=/auth/v1/verify
MAILER_URLPATHS_CONFIRMATION=/auth/v1/verify
MAILER_URLPATHS_RECOVERY=/auth/v1/verify
MAILER_URLPATHS_EMAIL_CHANGE=/auth/v1/verify
# --- Optional: PostgREST ---
PGRST_DB_SCHEMAS=public,storage,graphql_public
PGRST_DB_MAX_ROWS=1000
PGRST_DB_EXTRA_SEARCH_PATH=public,extensions
# --- Optional: Storage ---
STORAGE_TENANT_ID=stub
REGION=local
GLOBAL_S3_BUCKET=stub
IMGPROXY_AUTO_WEBP=true
# --- Optional: Analytics ---
LOGFLARE_PUBLIC_ACCESS_TOKEN=dein-logflare-token
# --- Optional: KI-Assistent in Studio ---
OPENAI_API_KEY=Verifizieren: Prüfe, dass kein Pflichtfeld leer oder auf dem Beispielwert geblieben ist:
grep -E "^(POSTGRES_PASSWORD|JWT_SECRET|ANON_KEY|SERVICE_ROLE_KEY|DASHBOARD_PASSWORD|SECRET_KEY_BASE|VAULT_ENC_KEY)=" .env
# Jede Zeile muss einen echten (nicht leeren) Wert zeigen.
# Kein Wert darf „your-super-secret..." oder „this_only_works_for" enthalten.Schritt 3: Stack starten
Bevor du den Stack zum ersten Mal startest, solltest du wissen, was dabei passiert: Docker lädt alle 11 Images (ca. 3–5 GB), PostgreSQL initialisiert die Datenbank mit den Init-SQL-Skripten und richtet Rollen, Extensions und Schemas ein. Dieser erste Start dauert je nach Hardware und Internetanbindung 5–15 Minuten.
# Images vorab herunterladen (optional, aber übersichtlicher)
docker compose pull
# Stack im Hintergrund starten
docker compose up -d
# Container-Status beobachten
docker compose psDie Container starten in einer festgelegten Reihenfolge, die durch depends_on-Bedingungen und Healthchecks gesteuert wird: Zuerst db, dann Auth/REST/Realtime/Storage/meta, dann Studio und zuletzt Kong. Das ist beabsichtigt – gib dem Stack 2–3 Minuten, bevor du den Status prüfst.
Verifizieren:
docker compose ps
# Erwartetes Ergebnis: alle Container mit Status "Up" oder "(healthy)"
# Beispielausgabe (gekürzt):
# NAME IMAGE STATUS
# supabase-db-1 supabase/postgres:15.8.1.085 Up (healthy)
# supabase-kong-1 kong/kong:3.9.1 Up (healthy)
# supabase-studio-1 supabase/studio:2026.06... Up (healthy)
# supabase-auth-1 supabase/gotrue:v2.189.0 Up (healthy)
# supabase-rest-1 postgrest/postgrest:v14.12 Up
# supabase-realtime-1 supabase/realtime:v2.102.3 Up (healthy)
# supabase-storage-1 supabase/storage-api:v1.60.4 Up (healthy)
# supabase-supavisor-1 supabase/supavisor:2.9.5 Up (healthy)
# HTTP-Antwort des API-Gateways prüfen
curl -I http://localhost:8000
# Erwartete Antwort: HTTP/1.1 200 OK (oder 401 – beides bedeutet: Kong antwortet)Taucht ein Container mit Status Exit oder Restarting auf, wirf zuerst einen Blick in seine Logs:
docker compose logs auth --tail=50
docker compose logs db --tail=50Schritt 4: Dashboard aufrufen und erste Einrichtung
Öffne im Browser http://deine-server-ip:8000. Kong leitet dich automatisch zum Studio weiter. Du wirst nach Benutzername und Passwort gefragt – das sind die Werte, die du in Schritt 2 als DASHBOARD_USERNAME und DASHBOARD_PASSWORD gesetzt hast.
Im Dashboard findest du sofort alles, was du für ein vollständiges Backend brauchst:
- Table Editor: Tabellen anlegen, bearbeiten und abfragen – ohne SQL-Kenntnisse.
- Authentication: Benutzer verwalten, OAuth-Provider konfigurieren (Google, GitHub, Apple usw.), E-Mail-Templates anpassen.
- Storage: Buckets anlegen und Dateien hochladen. Der Speicher landet unter
./volumes/storage/. - Edge Functions: Deno-Funktionen direkt im Browser schreiben oder über das Filesystem deployen.
- SQL Editor: Direkter SQL-Zugang zur PostgreSQL-Datenbank.
- API Docs: Automatisch generierte Dokumentation deiner REST-API – inklusive Client-Code-Beispielen.
Die wichtigsten API-Keys findest du unter Settings → API: den anon key (für öffentliche Client-Aufrufe) und den service_role key (nur für serverseitige Operationen – niemals im Frontend verwenden).
Verifizieren:
# REST-API-Health prüfen
curl http://localhost:8000/rest/v1/ \
-H "apikey: DEIN_ANON_KEY" \
-H "Authorization: Bearer DEIN_ANON_KEY"
# Erwartete Antwort: JSON-Objekt mit "swagger"-Feld
# Auth-Health prüfen
curl http://localhost:8000/auth/v1/health
# Erwartete Antwort: {"status":"alive"}Schritt 5: Edge Functions deployen
Edge Functions laufen in der Deno-Laufzeitumgebung und sind der Weg für serverseitige Logik, Webhooks und Integrationen. Eine neue Funktion legst du einfach als TypeScript-Datei im Dateisystem ab – kein Neustart des gesamten Stacks erforderlich, nur der Functions-Container muss neu starten:
# Neue Funktion anlegen
mkdir -p ./volumes/functions/hello-world
cat > ./volumes/functions/hello-world/index.ts << 'EOF'
Deno.serve(async (req) => {
const { name } = await req.json()
return new Response(
JSON.stringify({ message: `Hallo, ${name}!` }),
{ headers: { 'Content-Type': 'application/json' } }
)
})
EOF
# Nur den Functions-Container neu starten
docker compose restart functionsVerifizieren:
curl -X POST http://localhost:8000/functions/v1/hello-world \
-H "Authorization: Bearer DEIN_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Welt"}'
# Erwartete Antwort: {"message":"Hallo, Welt!"}Schritt 6: HTTPS und Reverse Proxy (Produktivbetrieb)
Für den Betrieb mit einer eigenen Domain und HTTPS enthält das offizielle Repository fertige Compose-Override-Dateien. Die Caddy-Variante ist für die meisten Setups am einfachsten, da sie Let's-Encrypt-Zertifikate vollautomatisch bezieht und erneuert. Details zu Caddy als Reverse Proxy findest du in der Anleitung Caddy als Reverse Proxy einrichten.
# PROXY_DOMAIN in .env setzen
echo "PROXY_DOMAIN=supabase.deine-domain.de" >> .env
# Stack mit Caddy-Override starten
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -dPasse außerdem SUPABASE_PUBLIC_URL und API_EXTERNAL_URL in der .env auf die neue HTTPS-URL an – andernfalls scheitern OAuth-Callbacks und Auth-E-Mail-Links.
Alternativ kannst du den bestehenden Nginx Proxy Manager nutzen, wenn er bereits in deinem Stack läuft: Lege einen Proxy-Host an, der auf http://kong:8000 (bzw. die interne Container-IP) zeigt, und lass NPM das SSL-Zertifikat via Let's Encrypt beziehen.
Verifizieren:
curl -I https://supabase.deine-domain.de
# Erwartete Antwort: HTTP/2 200 (oder 301/302 Redirect zum Dashboard)
# TLS-Zertifikat prüfen:
curl -v https://supabase.deine-domain.de 2>&1 | grep "SSL certificate"Schritt 7: Updates einspielen
Supabase veröffentlicht ca. einmal pro Monat neue Releases. Die aktuellen Image-Tags stehen immer in der docker-compose.yml im offiziellen Repository. Prüfe vor jedem Update die CHANGELOG.md auf Breaking Changes.
# Neueste Image-Tags aus dem offiziellen Repo holen
git pull
# Aktuelle CHANGELOG auf Breaking Changes prüfen
cat CHANGELOG.md | head -100
# Alle Images aktualisieren und Container neu erstellen
docker compose pull
docker compose up -d --force-recreate
# Status nach Update prüfen
docker compose psEinzelne Services lassen sich auch gezielt aktualisieren, ohne den ganzen Stack zu stoppen:
# Nur Auth neu starten (Beispiel)
docker compose up -d --force-recreate authVerifizieren:
docker compose ps
# Alle Container sollten "Up" oder "(healthy)" zeigen.
# Zeitstempel in der Spalte "Created" zeigen das Update-Datum.
curl http://localhost:8000/auth/v1/health
# {"status":"alive"}Schritt 8: Backup-Strategie
Die kritischen Daten liegen in drei Bereichen: den PostgreSQL-Dateien, dem Storage-Verzeichnis und der .env-Datei. Für eine solide Backup-Grundlage empfiehlt sich die Anleitung zur 3-2-1-Backup-Strategie.
# Datenbank-Dump (konsistenter Snapshot)
docker compose exec db pg_dumpall -U postgres > backup_$(date +%Y%m%d).sql
# Storage-Dateien sichern (rsync-Beispiel)
rsync -av ./volumes/storage/ /backup/supabase-storage/
# .env sichern (verschlüsselt!)
gpg --symmetric --cipher-algo AES256 -o /backup/supabase-env.gpg .envAutomatisierte PostgreSQL-Backups mit pg_dump, Rotation und Cloud-Sync beschreibt die Anleitung MySQL & PostgreSQL Backup automatisieren ausführlich.
Verifizieren:
ls -lh backup_*.sql
# Datei sollte mindestens einige KB groß sein (bei leerer DB ca. 20-50 KB)Troubleshooting / Typische Fehler
bad interpreter: /bin/bash^M(Kong startet nicht): CRLF-Zeilenenden in Shell-Skripten – passiert beim Git-Clone unter Windows ohnecore.autocrlf false. Lösung:find ./volumes -name "*.sh" | xargs dos2unixoder neu klonen mitgit config core.autocrlf false.401 Unauthorizedam Dashboard trotz korrektem Passwort:DASHBOARD_PASSWORDbesteht aus reinen Zahlen. Kong Basic-Auth lehnt numerische Passwörter ab. Lösung: Passwort in.envändern (muss mindestens einen Buchstaben enthalten), danachdocker compose up -d --force-recreate kong.invalid configuration: jwt_secret must be at least 32 characters(Auth startet nicht):JWT_SECRETist zu kurz. Lösung:sh utils/generate-keys.shausführen undJWT_SECRETin.envaktualisieren.- Services schlagen fehl nach Passwort-Änderung in
.env: Wenn./volumes/db/data/bereits existiert, ignoriert PostgreSQL Init-Skripte beim Neustart – die DB hat noch das alte Passwort. Lösung: In psql einloggen undALTER ROLE postgres PASSWORD 'neues-passwort';ausführen. Nicht das Datenverzeichnis löschen – das vernichtet alle Daten. - Port 5432 bereits belegt: Eine lokale PostgreSQL-Installation nutzt denselben Port. Lösung:
POSTGRES_PORT=5433in.envsetzen und alle Referenzen anpassen. - Vector/Analytics-Container unhealthy: Unter Podman oder rootless Docker fehlt
/var/run/docker.sock. Lösung:DOCKER_SOCKET_LOCATION=/run/podman/podman.sockin.envergänzen. - OAuth-Callbacks schlagen fehl / Auth-E-Mails mit falscher URL:
SUPABASE_PUBLIC_URLzeigt noch auflocalhost. Lösung: Auf die echte Server-IP oder Domain (inkl. Port) setzen, danndocker compose up -d --force-recreate auth studio. exec format errorbei ARM64-Hosts: Ältere gepinnte Image-Tags fehlten für arm64. Lösung: Image-Tags auf die aktuellen Versionen aus der offiziellendocker-compose.ymlaktualisieren (alle aktuellen Images sind arm64-kompatibel).
Häufige Fragen
Wie verbinde ich mich direkt mit PostgreSQL?
Über Supavisor im Session-Mode auf Port 5432 – dieser Modus eignet sich für persistente Verbindungen mit Tools wie pgAdmin oder DBeaver:
psql 'postgres://postgres.DEIN_POOLER_TENANT_ID:DEIN_POSTGRES_PASSWORD@deine-server-ip:5432/postgres'Für kurzlebige Verbindungen (serverless Functions, APIs) nimmst du den Transaction-Mode auf Port 6543. POOLER_TENANT_ID muss in der .env gesetzt sein und in den Verbindungsstring als Benutzername-Suffix eingehen.
Wie deploye ich eine Edge Function in Produktion?
Leg die TypeScript-Datei unter ./volumes/functions/FUNKTIONSNAME/index.ts ab und starte den Functions-Container neu: docker compose restart functions. Die Funktion ist danach sofort unter http://deine-domain:8000/functions/v1/FUNKTIONSNAME erreichbar. Für JWT-Schutz FUNCTIONS_VERIFY_JWT=true in .env setzen.
Kann ich den S3-Storage durch echtes S3 oder MinIO ersetzen?
Ja. Das Repo enthält docker-compose.s3.yml als Override für S3-kompatible Backends. Setze in .env: STORAGE_BACKEND=s3, GLOBAL_S3_BUCKET, REGION sowie AWS-/MinIO-Zugangsdaten. Ein eigenes MinIO-Setup beschreibt die Anleitung MinIO S3 selbst hosten mit Docker.
Wie konfiguriere ich E-Mail-Versand für Auth-Mails?
Trag deine SMTP-Zugangsdaten in .env ein (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_ADMIN_EMAIL) und starte danach den Auth-Container neu: docker compose restart auth. Für lokale Tests empfiehlt sich Mailpit oder Mailhog als SMTP-Catch-All-Container. In Entwicklungsumgebungen kann ENABLE_EMAIL_AUTOCONFIRM=true die E-Mail-Bestätigung vollständig überspringen.
Wie erkenne ich, welche Container-Version gerade läuft?
docker compose images
# Zeigt alle Images mit Repository, Tag und GrößeWie stoppe ich den Stack, ohne Daten zu verlieren?
# Nur Container stoppen, Volumes bleiben erhalten
docker compose down
# Container + anonyme Volumes entfernen (NICHT die benannten Volumes db-config/deno-cache)
docker compose down --volumesAchtung: docker compose down -v entfernt benannte Volumes (db-config, deno-cache), aber nicht den Bind-Mount ./volumes/db/data/. Die eigentlichen PostgreSQL-Daten sind also sicher – trotzdem lieber nur docker compose down ohne Flags verwenden.
Fazit
Supabase ist als selbst gehostete Firebase-Alternative bemerkenswert vollständig: Statt ein Dutzend Einzeldienste zu kombinieren, bekommst du PostgreSQL, Auth, REST-API, Realtime, Storage und Edge Functions als fertig verdrahtetes Paket. Die 11-Container-Architektur mag auf den ersten Blick erschlagen, aber jeder Container hat eine klar definierte Rolle – und dank Healthchecks und depends_on-Ketten startet der Stack in der richtigen Reihenfolge ohne manuelles Eingreifen.
Der größte Vorteil gegenüber dem verwalteten Supabase-Cloud-Angebot ist die vollständige Datenkontrolle: PostgreSQL läuft auf deinem Server, Backups liegen bei dir, und du bestimmst, wer Zugriff hat. Der Nachteil ist der Betriebsaufwand: Updates, Monitoring und Absicherung liegen in deiner Verantwortung. Für Produktivumgebungen lohnen sich ein Monitoring-Stack und automatisierte Backups von Tag eins an.
Wer Supabase als Datenbank-Backend für Anwendungen nutzt, profitiert davon, dass PostgREST automatisch eine REST-API aus jedem PostgreSQL-Schema generiert – ohne eine einzige Zeile Backend-Code. Für KMU-Anwendungen, Prototypen und interne Tools ist das ein erheblicher Produktivitätsgewinn.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
- PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
- MinIO S3 selbst hosten mit Docker: Compose-Anleitung mit Traefik und HTTPS
- Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
- MySQL & PostgreSQL Backup automatisieren mit cron: pg_dump, Rotation und rclone-Cloud-Sync
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
Offizielle Quellen: Supabase Self-Hosting with Docker (offizielle Dokumentation) | supabase/supabase GitHub – Docker-Verzeichnis.