External Supabase (BYO data plane)
The default self-host bundle includes Supabase OSS — Postgres, GoTrue, PostgREST, Realtime, Storage, Kong. If you already operate Supabase elsewhere (hosted Supabase Cloud, managed Postgres + the Supabase services on Kubernetes, a separate VM), you can point this stack at it and skip the bundled containers entirely.
When to BYO
- You already have a managed Postgres with backups + monitoring you trust more than what this bundle ships.
- You're consolidating multiple apps on one Supabase project (CCD- Suite is one of many).
- You're running at a scale where bundled single-node Postgres is going to bottleneck.
- You're on hosted Supabase Cloud and want to keep using their dashboard / branching / point-in-time recovery.
How
1. Comment out the bundled Supabase services
In your install dir's docker-compose.yml, comment out (or delete) the
following services:
# db:
# auth:
# rest:
# realtime:
# storage:
# kong:
# db-migrate:
Also remove their depends_on references from the four CCD app
services (web, api-gateway, ai-services, worker):
web:
depends_on:
# db-migrate: ← remove
# condition: service_completed_successfully
# kong: ← remove
# condition: service_started
ollama:
condition: service_healthy
2. Point at your external Supabase
In .env:
# All three URLs point at your external Supabase API gateway
# (the host that fronts GoTrue/PostgREST/Realtime/Storage).
SUPABASE_URL=https://api.your-supabase.example.com
NEXT_PUBLIC_SUPABASE_URL=https://api.your-supabase.example.com
SUPABASE_PUBLIC_URL=https://api.your-supabase.example.com
# Keys from your Supabase project's API settings.
SUPABASE_ANON_KEY=eyJhbGciOi...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOi...
SUPABASE_JWT_SECRET=<the JWT secret from your project>
If you're on hosted Supabase Cloud:
SUPABASE_URL=https://<project-ref>.supabase.coSUPABASE_ANON_KEY= theanon publickey from Project Settings → APISUPABASE_SERVICE_ROLE_KEY= theservice_role secretkey from the same pageSUPABASE_JWT_SECRET= JWT Settings → JWT Secret
3. Run migrations against the external DB
The bundled stack runs db-migrate automatically. With BYO, you run
the migrations once, before first boot:
# The migration files ship inside your self-host bundle — no source
# checkout needed. Work from your install directory:
cd ~/ccd
# Hosted Supabase Cloud
supabase link --project-ref <your-ref>
supabase db push
# Self-hosted Supabase / managed Postgres — use the bundled migrator
# instead, pointing at your external DB:
export PGHOST=<host> PGPORT=5432 PGUSER=postgres PGPASSWORD=<...> PGDATABASE=postgres
docker compose run --rm db-migrate
(The db-migrate compose service is an idempotent psql runner —
the same one the bundle uses internally — that tracks applied
migrations in a _ccd_migrations ledger table.)
4. Start the slim stack
cd <your-install-dir>
docker compose up -d
Only ollama, ollama-preload, and the four CCD app services start.
The data plane lives at your external Supabase.
Caveats
-
pg_cron— some CCD background jobs use Postgres cron viapg_cron. Hosted Supabase enablespg_cronon request; self-hosted Supabase has it built into thesupabase/postgresimage. If your external Postgres doesn't havepg_cron, those jobs fall back to the worker's BullMQ scheduler (less efficient but functional). -
pgvectordimensions — the knowledge-graph embedding column isvector(1536)to match cloud'stext-embedding-3-small. If you're on a different embedding model (768-dim Ollama default, 1024-dim mxbai), semantic search falls through topg_trgmfuzzy matching. See Hardware sizing for the dimension contract. -
Realtime — if your external Supabase has Realtime disabled, the CCD UI's realtime layer falls back to polling. UI still works, feels less live.
-
Storage — bucket policies are CCD-Suite's responsibility. The migrations create the buckets we need; you don't need to bootstrap them by hand.
Hybrid: external Postgres only, bundled Supabase services
A middle ground: keep the bundled auth/rest/realtime/storage/
kong services but point them at an external Postgres. Edit each
service's DB_* env vars in docker-compose.yml to your external
host. The db-migrate sidecar still runs against the external DB.
Useful when you want managed Postgres (RDS, Cloud SQL, etc.) without running your own Supabase application layer.