This repository provides a self-hosted Supabase stack using Docker Compose, including Postgres, Auth (GoTrue), PostgREST, Realtime, Storage, Imgproxy, Studio, Supavisor (connection pooler), Edge Functions, Analytics (Logflare), and Kong as an API gateway.
Read the official docs for deeper configuration: Self-hosting with Docker.
- Configure environment
cp env.example .env
# Open .env and set at least: POSTGRES_PASSWORD, JWT_SECRET
- Start services
docker compose up -d
- Stop / Destroy
docker compose down
# To also remove volumes & orphans used in dev helpers
docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans
- Reset everything (local only)
./reset.sh
The following services are defined in docker-compose.yml:
-
studio (
supabase-studio)- Web UI to manage your project (DB tables, auth, storage, SQL, logs).
- Env: connects to
metafor metadata, relies on Kong URL, anon/service keys. - Healthcheck probes the internal Studio API.
-
kong (
supabase-kong)- API gateway fronting core services under a single base URL.
- Declarative config loaded from
volumes/api/kong.yml(templated at container start). - Exposes HTTP/HTTPS ports from
.env(KONG_HTTP_PORT,KONG_HTTPS_PORT).
-
auth (
supabase-auth/ GoTrue)- Authentication and user management.
- Uses
GOTRUE_DB_DATABASE_URLpointing to Postgres; JWT secret/exp from.env. - Email/phone flows configurable via SMTP and flags in
.env.
-
rest (
supabase-rest/ PostgREST)- Auto-generated REST API from Postgres.
- Uses
PGRST_DB_URIwith roleauthenticatorand JWT secret for auth.
-
realtime (
realtime-dev.supabase-realtime)- Realtime change broadcasts via websockets.
- Connects to Postgres schema
_realtime; secured viaAPI_JWT_SECRET.
-
storage (
supabase-storage)- File storage API with optional image transformations via Imgproxy.
- Uses
DATABASE_URLand PostgREST URL, expects anon/service keys. - Stores files locally under
volumes/storageby default.
-
imgproxy (
supabase-imgproxy)- On-the-fly image resizing/transformations for Storage assets.
- Reads from local filesystem mounted at
/and uses port 5001.
-
meta (
supabase-meta/ Postgres Meta)- Metadata API for Studio; connects to Postgres using
supabase_admin.
- Metadata API for Studio; connects to Postgres using
-
functions (
supabase-edge-functions/ Edge Runtime)- Runs Deno-based Edge Functions from
volumes/functions. - Uses Supabase URL/keys and DB URL;
VERIFY_JWTcan be toggled.
- Runs Deno-based Edge Functions from
-
analytics (
supabase-analytics/ Logflare)- Centralized logs/analytics with a Postgres backend in
_supabase. - Exposes port 4000; Studio uses it for project analytics.
- Centralized logs/analytics with a Postgres backend in
-
db (
supabase-db/ Postgres)- Postgres 15 with Supabase extensions and initialization SQL.
- Mounts SQL init/migration files from
volumes/db/*.sql. - Data persisted under
volumes/db/data(ignored by git).
-
vector (
supabase-vector)- Vector is a log forwarder/shipper used by Analytics.
- Config from
volumes/logs/vector.yml.
-
supavisor (
supabase-pooler)- Connection pooler / Postgres proxy for multi-tenant workloads.
- Config from
volumes/pooler/pooler.exs; exposes DB and proxy ports.
Kong acts as the single entrypoint. It reads a rendered config from volumes/api/kong.yml (templated at startup to inject environment values). Studio and clients should use the Kong base URL (see .env KONG_HTTP_PORT and SUPABASE_PUBLIC_URL).
Common endpoints via Kong (examples):
- Auth:
/auth/* - REST (PostgREST):
/rest/* - Realtime:
/realtime/* - Storage:
/storage/* - Edge Functions:
/functions/*
Refer to volumes/api/kong.yml to see the full route map.
Copy env.example to .env and set values. Important variables:
POSTGRES_PASSWORD(required): Postgres superuser password.POSTGRES_DB,POSTGRES_PORT,POSTGRES_HOST: DB connection parameters.JWT_SECRET,JWT_EXPIRY: Shared JWT secret and expiration used across services.ANON_KEY,SERVICE_ROLE_KEY: JWTs signed byJWT_SECRETwith rolesanonandservice_role.SUPABASE_PUBLIC_URL,SITE_URL,API_EXTERNAL_URL: External URLs used by Studio/Auth/Kong.- SMTP settings to enable email auth flows.
If you need help generating dev ANON_KEY / SERVICE_ROLE_KEY tokens signed by your JWT_SECRET, ask and we’ll generate them.
This repo keeps configuration and SQL migration/init files in version control and ignores runtime data:
volumes/api/kong.yml(Kong declarative config)volumes/db/*.sql(DB init/migrations)volumes/logs/vector.yml(Vector config)volumes/pooler/pooler.exs(Supavisor config)volumes/functions/(Edge functions source)- Postgres data directory:
volumes/db/data/is ignored (local state only)
See .gitignore for complete rules.
Check container health and logs:
docker compose ps
docker compose logs <service>
Some services have HTTP health endpoints (e.g., Auth: http://localhost:9999/health, Analytics: http://localhost:4000/health).
You can point services at an external Postgres by setting POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_PASSWORD and commenting out the db service. Ensure schemas, roles, and required extensions are provisioned (migrate the SQL under volumes/db/*.sql).
- Migrations not applied: confirm SQL files are mounted and Postgres is healthy before dependents start.
- 401/403 from REST/Storage: verify
ANON_KEY/SERVICE_ROLE_KEYare signed byJWT_SECRETand have correctroleclaim. - Realtime not emitting changes: ensure
realtimeschema andDB_AFTER_CONNECT_QUERYare set; check JWT secret alignment. - Studio errors: verify
STUDIO_PG_META_URL,SUPABASE_PUBLIC_URL, and Kong routes.
The header in docker-compose.yml includes example commands to run with additional dev overrides (./dev/docker-compose.dev.yml) and a reset.sh script to wipe local state.