Skip to content

feat: self-hosted supabase data plane for enterprise edge (#231) - #240

Merged
sakibsadmanshajib merged 7 commits into
mainfrom
feat/231-selfhosted-dataplane
Jun 25, 2026
Merged

sakibsadmanshajib merged 7 commits into
mainfrom
feat/231-selfhosted-dataplane

Conversation

@sakibsadmanshajib

@sakibsadmanshajib sakibsadmanshajib commented Jun 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

Closes #231. Ships a fully self-hosted Supabase stack inside the enterprise compose profile so the EnterpriseEdge box has zero external SaaS dependency. This is the blocking foundation that unblocks RAG (#232).

  • supabase-db (pgvector/pgvector:pg16): Postgres 16 with the vector extension pre-installed. CREATE EXTENSION IF NOT EXISTS vector migration added so RAG (Carl.sh B: RAG — pgvector schema, local bge-m3 embeddings, /v1/rag/* endpoints #232) can run locally.
  • supabase-auth (supabase/gotrue:v2.170.0): local JWT issuer. SUPABASE_JWKS_URL and SUPABASE_JWT_ISSUER point at this service on the enterprise profile; apps/edge-api/internal/auth/jwt_supabase.go validates JWTs against the local issuer without code changes.
  • supabase-rest (postgrest/postgrest:v12.2.3): auto REST API over local Postgres, used as SUPABASE_URL by control-plane.
  • supabase-storage (supabase/storage-api:v1.11.13): S3-compatible object storage with a local filesystem backend. No MinIO (AGPL avoided per repo policy). hive-files and hive-images buckets are created by a one-shot supabase-init container on first compose up.
  • deploy/supabase/init/00-extensions.sql: Postgres init script enabling uuid-ossp, pgcrypto, vector; creating auth, storage, graphql_public, extensions schemas; and creating the anon, authenticated, service_role, supabase_admin roles required by GoTrue and PostgREST.
  • supabase/migrations/20260625_01_enable_pgvector.sql: idempotent CREATE EXTENSION IF NOT EXISTS vector. Safe on both self-hosted and hosted Supabase.
  • .env.example: ENTERPRISE_* variable block with generation instructions and a commented rewire block for SUPABASE_URL, SUPABASE_DB_URL, SUPABASE_JWKS_URL, S3_ENDPOINT, and related vars.
  • edge-api and control-plane gain required: false depends_on entries for the new services so enterprise profile waits for local services before starting application containers.

The local, cloud, and chat profiles are unchanged and continue to use hosted Supabase.

Verification

  • docker compose --profile enterprise config exits 0 (YAML valid, no interpolation errors).
  • docker compose --profile local config exits 0 (existing profile unaffected).
  • docker compose --profile cloud config exits 0 (existing profile unaffected).
  • Mandatory guards removed from compose interpolation path (:? replaced with :-) because Docker Compose evaluates all service envs regardless of active profile; empty-value failure is enforced at runtime by Postgres refusing to start with a blank password.
  • pgvector live test (pulling the image and running SELECT extname FROM pg_extension WHERE extname='vector') was not run in this session due to image pull time and cost constraints. The pgvector/pgvector:pg16 image ships the extension pre-installed per the upstream README; the init SQL and migration are both idempotent.

Test plan

  • Run docker compose --profile enterprise config and confirm exit 0.
  • Set ENTERPRISE_DB_PASSWORD, ENTERPRISE_JWT_SECRET, ENTERPRISE_ANON_KEY, ENTERPRISE_SERVICE_ROLE_KEY and bring up the enterprise profile.
  • Confirm supabase-db healthcheck passes and SELECT extname FROM pg_extension WHERE extname='vector' returns a row.
  • Confirm supabase-auth health endpoint responds at http://localhost:9999/health.
  • Confirm supabase-init exits 0 and both hive-files and hive-images buckets exist.
  • Apply supabase/migrations/20260625_01_enable_pgvector.sql against the local Postgres and confirm idempotency on re-run.
  • Confirm local and cloud profiles still start correctly with hosted Supabase credentials.

Summary by CodeRabbit

  • New Features

    • Added an enterprise self-hosted data plane setup for Supabase, including local auth, storage, and database services.
    • Enabled vector database support for enterprise deployments.
  • Documentation

    • Expanded setup and environment guidance for enterprise deployments.
    • Updated install and startup instructions to use the full compose stack explicitly.

Greptile Summary

This PR ships a fully self-hosted Supabase data plane (Postgres/pgvector, GoTrue, PostgREST, Supabase Storage) inside a new docker-compose.enterprise.yml override file, enabling the EnterpriseEdge profile to run without any external SaaS dependency and unblocking RAG (#232).

  • New services: supabase-db (pgvector:pg16), supabase-auth (GoTrue v2.170.0), supabase-rest (PostgREST v12.2.3), supabase-storage (v1.11.13), and a one-shot supabase-init container that creates the hive-files/hive-images buckets via the Storage API.
  • Compose split: Enterprise services are in a separate file to avoid :? interpolation errors for operators running the local/cloud profiles without ENTERPRISE_* vars set; install.sh, CLAUDE.md, and operator docs are all updated to pass both -f flags.
  • Init SQL + migration: 00-extensions.sql bootstraps extensions, schemas, and roles on first Postgres start; 20260625_01_enable_pgvector.sql adds the idempotent pgvector migration for both self-hosted and hosted Supabase.

Confidence Score: 3/5

The core compose orchestration is sound, but two concrete runtime failures exist: Open WebUI OIDC login is broken for the enterprise profile, and the S3 endpoint path documented in the compose file comment contradicts the correct path in .env.example.

The OIDC discovery URL for Open WebUI is constructed by appending /auth/v1/.well-known/openid-configuration to SUPABASE_URL. For cloud deployments this is correct (Kong gateway routing), but for the enterprise profile SUPABASE_URL points directly at GoTrue which does not expose the /auth/v1/ prefix — every user login via Open WebUI returns an OIDC discovery error. Separately, the comment inside docker-compose.enterprise.yml documents the S3 endpoint as /object/s3 while the correct Supabase Storage S3-compatible path is /storage/v1/s3; an operator following only the compose file comment would configure a non-functional storage endpoint.

deploy/docker/docker-compose.yml (OPENID_PROVIDER_URL construction) and deploy/docker/docker-compose.enterprise.yml (S3 endpoint path comment).

Important Files Changed

Filename Overview
deploy/docker/docker-compose.enterprise.yml New enterprise override defining supabase-db, supabase-auth, supabase-rest, supabase-storage, and supabase-init services; the S3 endpoint path in a guiding comment is wrong (/object/s3 vs /storage/v1/s3), and the OIDC issue in the base file compounds the problem here since no open-webui override is provided.
deploy/docker/docker-compose.yml Adds informational comments for enterprise profile configuration and depends_on stubs for new services; the hardcoded OPENID_PROVIDER_URL construction from SUPABASE_URL breaks Open WebUI OIDC for the enterprise profile where GoTrue is accessed directly.
deploy/supabase/init/00-extensions.sql Idempotent Postgres init script creating required extensions (uuid-ossp, pgcrypto, vector), schemas (auth, storage, graphql_public, extensions), and roles (anon, authenticated, service_role, supabase_admin, hive_app) — well-structured with proper IF NOT EXISTS guards.
supabase/migrations/20260625_01_enable_pgvector.sql Single idempotent CREATE EXTENSION IF NOT EXISTS vector migration, safe to run on both self-hosted and hosted Supabase.
.env.example Adds a detailed ENTERPRISE_* variable block with generation instructions; the rewire block has the correct S3 and OIDC paths, but the OPENID_PROVIDER_URL override is commented-out and cannot override the hardcoded Compose interpolation without a service-level override in the enterprise compose file.
scripts/install.sh Updated to pass both -f flags for enterprise profile in all relevant docker compose invocations (start, stop, and diagnostic banners).
CLAUDE.md Updated enterprise startup command to include both -f flags, keeping documentation in sync with the new two-file compose pattern.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Op as Operator
    participant DB as supabase-db (pgvector:pg16)
    participant Auth as supabase-auth (GoTrue)
    participant Rest as supabase-rest (PostgREST)
    participant Stor as supabase-storage
    participant Init as supabase-init (one-shot)
    participant EA as edge-api
    participant CP as control-plane

    Op->>DB: compose up --profile enterprise
    DB-->>DB: run 00-extensions.sql (schemas, roles, vector)
    DB-->>Auth: service_healthy
    DB-->>Rest: service_healthy
    Auth-->>Auth: GoTrue internal DB migrations
    Rest-->>Stor: service_healthy
    DB-->>Stor: service_healthy
    Stor-->>Init: service_healthy
    Init->>Stor: POST /bucket hive-files (service_role JWT)
    Init->>Stor: POST /bucket hive-images (service_role JWT)
    Init-->>EA: service_completed_successfully
    Init-->>CP: service_completed_successfully
    EA-->>EA: start
    CP-->>CP: start
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Op as Operator
    participant DB as supabase-db (pgvector:pg16)
    participant Auth as supabase-auth (GoTrue)
    participant Rest as supabase-rest (PostgREST)
    participant Stor as supabase-storage
    participant Init as supabase-init (one-shot)
    participant EA as edge-api
    participant CP as control-plane

    Op->>DB: compose up --profile enterprise
    DB-->>DB: run 00-extensions.sql (schemas, roles, vector)
    DB-->>Auth: service_healthy
    DB-->>Rest: service_healthy
    Auth-->>Auth: GoTrue internal DB migrations
    Rest-->>Stor: service_healthy
    DB-->>Stor: service_healthy
    Stor-->>Init: service_healthy
    Init->>Stor: POST /bucket hive-files (service_role JWT)
    Init->>Stor: POST /bucket hive-images (service_role JWT)
    Init-->>EA: service_completed_successfully
    Init-->>CP: service_completed_successfully
    EA-->>EA: start
    CP-->>CP: start
Loading

Reviews (5): Last reviewed commit: "docs: fix two comment inconsistencies in..." | Re-trigger Greptile

Add a fully self-hosted Supabase stack to the enterprise compose profile so
the EnterpriseEdge box has zero external SaaS dependency. Tenant data,
authentication tokens, and uploaded files never leave the customer machine.

Services added (enterprise profile only):
- supabase-db (pgvector/pgvector:pg16): Postgres 16 with the vector
  extension pre-installed. Required by RAG (#232).
- supabase-auth (supabase/gotrue:v2.170.0): local JWT issuer. edge-api
  JWKS validation points at this service via SUPABASE_JWKS_URL.
- supabase-rest (postgrest/postgrest:v12.2.3): auto REST API over the
  local Postgres, used by control-plane as SUPABASE_URL.
- supabase-storage (supabase/storage-api:v1.11.13): S3-compatible object
  storage with a local filesystem backend (no MinIO, AGPL avoided).
  Replaces the hosted Supabase Storage S3 endpoint for the enterprise path.
- supabase-init: one-shot curl container that creates the hive-files and
  hive-images buckets via the Storage API on first compose up.

Other changes:
- deploy/supabase/init/00-extensions.sql: Postgres init script that
  enables uuid-ossp, pgcrypto, and vector extensions and creates the auth,
  storage, graphql_public, and extensions schemas plus the anon,
  authenticated, service_role, and supabase_admin roles on first boot.
- supabase/migrations/20260625_01_enable_pgvector.sql: idempotent
  CREATE EXTENSION IF NOT EXISTS vector migration. Safe to run on both
  the self-hosted and hosted Supabase instances.
- .env.example: ENTERPRISE_* variable block with generation instructions
  and commented rewire block for SUPABASE_URL, SUPABASE_DB_URL,
  SUPABASE_JWKS_URL, S3_ENDPOINT, and related vars.
- edge-api and control-plane services gain required:false depends_on
  entries for supabase-auth, supabase-storage, and supabase-db so the
  enterprise profile waits for local services before starting application
  containers.

Profiles local, cloud, and chat are not changed and continue to use the
hosted Supabase configuration as before.

Closes #231
@gitguardian

gitguardian Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 10 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
34282787 Triggered Generic Password 46aaf7f deploy/docker/docker-compose.yml View secret
34282788 Triggered Generic Password 46aaf7f .env.example View secret
34282788 Triggered Generic Password 46aaf7f deploy/docker/docker-compose.yml View secret
34282789 Triggered Generic Password 46aaf7f deploy/docker/docker-compose.yml View secret
34282788 Triggered Generic Password 46aaf7f deploy/docker/docker-compose.yml View secret
34282789 Triggered Generic Password 46aaf7f deploy/docker/docker-compose.yml View secret
34282880 Triggered Generic Password d67aa62 deploy/docker/docker-compose.enterprise.yml View secret
34282880 Triggered Generic Password d67aa62 deploy/docker/docker-compose.enterprise.yml View secret
34282880 Triggered Generic Password d67aa62 deploy/docker/docker-compose.enterprise.yml View secret
34282880 Triggered Generic Password d67aa62 deploy/docker/docker-compose.enterprise.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@sakibsadmanshajib, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 42 minutes and 14 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 991540a8-5cfc-4a5d-9ccd-44ce6c475d88

📥 Commits

Reviewing files that changed from the base of the PR and between bfb8ae5 and faadf64.

📒 Files selected for processing (1)
  • deploy/docker/docker-compose.yml
📝 Walkthrough

Walkthrough

This PR adds a local enterprise Supabase stack, updates startup instructions to use both compose files, bootstraps required Postgres objects, and enables the vector extension through a migration.

Changes

Enterprise self-hosted Supabase stack

Layer / File(s) Summary
Enterprise config and startup guidance
.env.example, deploy/docker/docker-compose.yml, CLAUDE.md, scripts/install.sh
Adds enterprise Supabase environment variables and updates startup comments and commands to reference both compose files.
Enterprise compose services
deploy/docker/docker-compose.enterprise.yml
Defines the enterprise-profile Postgres, GoTrue, PostgREST, Storage, and compose override wiring for the local Supabase stack.
Bootstrap and startup gating
deploy/docker/docker-compose.enterprise.yml
Adds the storage bucket initializer, waits for it before starting edge-api and control-plane, and declares persistent volumes.
Postgres bootstrap and vector migration
deploy/supabase/init/00-extensions.sql, supabase/migrations/20260625_01_enable_pgvector.sql
Creates extensions, schemas, roles, and grants for the local Supabase database, and enables vector via migration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped into compose with a merry little thump,
Found Supabase snug in the box, all bouncy and plump.
Vectors now burrow where the carrots grow bright,
And local auth twinkles in the CLI light.
Hop-hop hooray for a stack that feels just right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the enterprise self-hosted Supabase data plane change.
Linked Issues check ✅ Passed The PR adds local Postgres, Storage, Auth, env rewiring, and a vector migration in the enterprise profile, matching #231's requirements.
Out of Scope Changes check ✅ Passed All changes support the self-hosted enterprise Supabase stack and related startup wiring; no unrelated code paths appear modified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/231-selfhosted-dataplane

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

B1 (missing hive_app role): add hive_app NOLOGIN role to the DO block in
deploy/supabase/init/00-extensions.sql. RLS policies in migration
20260529_01_rls_tenant_tables.sql grant full access to this role; without
it the control-plane connection would fail all policy checks on first boot.
Also grant hive_app USAGE on public and storage schemas.

B2 (empty JWT secret auth bypass): all ENTERPRISE_JWT_SECRET,
ENTERPRISE_DB_PASSWORD, ENTERPRISE_ANON_KEY, and ENTERPRISE_SERVICE_ROLE_KEY
vars now use :? guards so a missing value refuses startup with a clear message.

Docker Compose constraint fix: :? guards in enterprise-only services cause
config validation errors for --profile local and --profile cloud because
Compose interpolates all service envs regardless of active profile. Resolved
by extracting the five Supabase services into a dedicated override file
deploy/docker/docker-compose.enterprise.yml that is only parsed when
explicitly included. The base docker-compose.yml retains the comment block
explaining the two-file usage pattern. local and cloud profiles now validate
cleanly without any ENTERPRISE_* vars set.

Verification:
  docker compose --profile local config: OK (no enterprise vars)
  docker compose --profile cloud config: OK (no enterprise vars)
  docker compose -f docker-compose.yml -f docker-compose.enterprise.yml
    --profile enterprise config (with vars): OK
  Same without vars: errors on ENTERPRISE_DB_PASSWORD as required
B3: scripts/install.sh used plain --profile enterprise on four invocations
(up, down, monitoring tip, logs tip). The self-hosted Supabase services live
in docker-compose.enterprise.yml which was never included, so supabase-db,
supabase-auth, supabase-rest, supabase-storage, and supabase-init never
started on an enterprise box, leaving the data plane silently absent.

All four install.sh invocations now pass both -f flags with absolute paths:
  -f "$HIVE_HOME/deploy/docker/docker-compose.yml"
  -f "$HIVE_HOME/deploy/docker/docker-compose.enterprise.yml"

CLAUDE.md Getting Started enterprise example updated to match.

GitGuardian false positive: the JWT payload JSON fragment in the
.env.example comment block (role/iss/iat keys) was triggering the scanner.
Replaced with a reference to the Supabase self-host key generator URL.
Classification: false positive, no real secret was committed, no rotation
needed.

Verified:
  docker compose -f docker-compose.yml -f docker-compose.enterprise.yml
    --profile enterprise config (with vars): OK
  docker compose --profile local config: OK
  docker compose --profile cloud config: OK
Comment thread deploy/docker/docker-compose.enterprise.yml Outdated
Comment thread deploy/docker/docker-compose.enterprise.yml Outdated
Comment thread deploy/docker/docker-compose.yml Outdated
Comment thread deploy/docker/docker-compose.enterprise.yml Outdated
Bug 1: entrypoint used \${SERVICE_KEY} which Compose interpolates at parse
time from the host env (empty string). Changed to \$\${SERVICE_KEY} so the
container shell expands it at runtime from the injected environment.

Bug 2: curl -sf ... || true swallowed 401/500/network errors, making a
broken Storage API look healthy. Replaced with explicit HTTP status capture;
2xx and 409 (already exists) succeed, any other status exits 1 so the init
container fails visibly instead of silently.

Bug 3: edge-api and control-plane could start before supabase-init finished
creating buckets, causing startup S3 checks to fail. Added
supabase-init: { condition: service_completed_successfully } to the
depends_on of both services in the override file only, so --profile local
and --profile cloud are unaffected.

Bug 4: GOTRUE_JWT_ISSUER defaulted to http://localhost:9999. edge-api
validates the iss claim against SUPABASE_JWT_ISSUER (http://supabase-auth:9999
on the enterprise profile), so every minted JWT failed the issuer check.
Changed default to http://supabase-auth:9999 to match.

Verified: enterprise/local/cloud compose config all exit 0.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d67aa62a27

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .env.example Outdated
Comment thread .env.example
Comment thread deploy/docker/docker-compose.yml
Comment thread deploy/docker/docker-compose.enterprise.yml Outdated
Comment thread deploy/supabase/init/00-extensions.sql
Comment thread deploy/docker/docker-compose.enterprise.yml Outdated
Comment thread deploy/docker/docker-compose.yml Outdated
Comment thread deploy/docker/docker-compose.enterprise.yml
Comment thread deploy/docker/docker-compose.enterprise.yml
Comment thread deploy/docker/docker-compose.enterprise.yml
- SUPABASE_URL comment corrected to point at GoTrue (supabase-auth:9999)
  not PostgREST; control-plane calls GET /auth/v1/user on this URL and
  PostgREST cannot serve auth/v1 routes.

- SUPABASE_JWKS_URL comment documents the HTTPS enforcement in
  edge-api/cmd/server/main.go and explains the TLS proxy requirement for
  production; LAN/dev workaround noted inline.

- S3_ENDPOINT path corrected from /object/s3 to /storage/v1/s3 to match
  the actual Supabase Storage S3-compatible endpoint path (confirmed from
  .env.example line 150 for hosted Supabase).

- API_EXTERNAL_URL added to supabase-auth: GoTrue v2 requires this var
  at startup for email link generation; missing it causes GoTrue to refuse
  to start.

- GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED + URI added to supabase-auth:
  without this flag GoTrue issues plain tokens with no tenant_id/role
  claims; every RLS policy and auth middleware check would fail.

- PostgREST healthcheck changed from wget (absent from the minimal image)
  to a bash /dev/tcp TCP probe which works with only the shell available.

Compose config: enterprise/local/cloud all exit 0.
Comment thread deploy/docker/docker-compose.enterprise.yml
…I fix)

docker-compose.yml had required:false depends_on entries for supabase-auth,
supabase-storage, and supabase-db. Docker Compose validates all depends_on
references at parse time regardless of the required flag — if the named
service does not exist in any loaded file the project fails with 'depends on
undefined service'. The local+tools profile only loads docker-compose.yml so
those enterprise-only services are undefined, breaking the gen-permissions
codegen step and cascading to web-console type+unit+build failure.

Fix: remove the three stubs. The enterprise ordering is fully handled inside
docker-compose.enterprise.yml (supabase-init depends_on chain covers db,
auth, rest, storage, init in order; edge-api and control-plane depend on
supabase-init via the override).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
.env.example (1)

253-253: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Quote placeholder values to prevent dotenv parsing errors.

The placeholder values at these lines contain spaces and special characters (<generate: openssl rand -base64 24>, <sign anon JWT with ENTERPRISE_JWT_SECRET>). While Docker Compose's env parser is lenient, standard dotenv tools and editors may truncate at the first space or flag syntax errors. Wrapping them in double quotes ensures they are treated as single values.

-ENTERPRISE_DB_PASSWORD=<generate: openssl rand -base64 24>
+ENTERPRISE_DB_PASSWORD="<generate: openssl rand -base64 24>"

-ENTERPRISE_JWT_SECRET=<generate: openssl rand -base64 48>
+ENTERPRISE_JWT_SECRET="<generate: openssl rand -base64 48>"

-ENTERPRISE_ANON_KEY=<sign anon JWT with ENTERPRISE_JWT_SECRET>
+ENTERPRISE_ANON_KEY="<sign anon JWT with ENTERPRISE_JWT_SECRET>"

-ENTERPRISE_SERVICE_ROLE_KEY=<sign service_role JWT with ENTERPRISE_JWT_SECRET>
+ENTERPRISE_SERVICE_ROLE_KEY="<sign service_role JWT with ENTERPRISE_JWT_SECRET>"

Also applies to: 260-260, 265-266

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.env.example at line 253, The placeholder values in the env template are
unquoted, which can break dotenv parsing when they contain spaces or special
characters. Update the affected entries in the .env.example placeholders so they
are wrapped in double quotes, including the ENTERPRISE_DB_PASSWORD and the JWT
signing placeholders near the ENTERPRISE_JWT_SECRET-related values. Keep the
changes localized to the placeholder lines so tools like dotenv, editors, and
parsers treat each placeholder as a single value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Around line 287-322: The S3 endpoint documentation is inconsistent between the
enterprise env example and the docker compose comment. Update the misleading
`/object/s3` reference in docker-compose.yml to match the correct Supabase
Storage S3 path `/storage/v1/s3`, and keep the wording aligned with the existing
`S3_ENDPOINT` guidance in `.env.example` so operators see the same endpoint in
both places.

In `@deploy/docker/docker-compose.enterprise.yml`:
- Around line 42-43: The GitGuardian failure is caused by the long operator
guidance embedded in the required env interpolation strings for the enterprise
compose file. Update the affected placeholders on the secret-bearing settings in
this docker-compose configuration to use neutral required markers like the
POSTGRES_PASSWORD entry, and move the explanatory setup text into comments or
the .env.example file instead. Apply the same cleanup to the other referenced
env blocks in this file so the runtime behavior stays the same while the scan no
longer flags the guidance strings.

In `@deploy/docker/docker-compose.yml`:
- Around line 175-194: The comments for SUPABASE_URL and S3_ENDPOINT in the
compose config are inconsistent with the documented enterprise endpoints. Update
the SUPABASE_URL guidance in the docker-compose enterprise environment block to
point to the GoTrue/auth service used by control-plane calls, and correct the
S3_ENDPOINT example to the Supabase Storage S3-compatible path. Use the existing
SUPABASE_URL, S3_ENDPOINT, and enterprise profile comment blocks to locate and
align the wording with .env.example.

In `@deploy/supabase/init/00-extensions.sql`:
- Around line 39-44: The bootstrap for hive_app creates a NOLOGIN role, but the
control-plane/edge-api connection contract expects this to be the actual
application DB role. Update the role setup in 00-extensions.sql so hive_app can
authenticate as intended, or change the downstream usage in the RLS migration
and related connection config to a separate login role consistently. Refer to
the hive_app role creation block and the RLS policy assumptions in the
tenant-tables migration when making the change.

---

Nitpick comments:
In @.env.example:
- Line 253: The placeholder values in the env template are unquoted, which can
break dotenv parsing when they contain spaces or special characters. Update the
affected entries in the .env.example placeholders so they are wrapped in double
quotes, including the ENTERPRISE_DB_PASSWORD and the JWT signing placeholders
near the ENTERPRISE_JWT_SECRET-related values. Keep the changes localized to the
placeholder lines so tools like dotenv, editors, and parsers treat each
placeholder as a single value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ade26b93-d469-44f0-b11b-b8891ed4ffbf

📥 Commits

Reviewing files that changed from the base of the PR and between f3d5caf and bfb8ae5.

📒 Files selected for processing (7)
  • .env.example
  • CLAUDE.md
  • deploy/docker/docker-compose.enterprise.yml
  • deploy/docker/docker-compose.yml
  • deploy/supabase/init/00-extensions.sql
  • scripts/install.sh
  • supabase/migrations/20260625_01_enable_pgvector.sql

Comment thread .env.example
Comment thread deploy/docker/docker-compose.enterprise.yml
Comment thread deploy/docker/docker-compose.yml
Comment thread deploy/supabase/init/00-extensions.sql
SUPABASE_URL comment: corrected from supabase-rest:3000 to supabase-auth:9999.
S3_ENDPOINT comment: corrected path from /object/s3 to /storage/v1/s3.
Both now match .env.example and docker-compose.enterprise.yml.
@sakibsadmanshajib
sakibsadmanshajib merged commit 6a6f912 into main Jun 25, 2026
14 of 16 checks passed
@sakibsadmanshajib
sakibsadmanshajib deleted the feat/231-selfhosted-dataplane branch June 25, 2026 23:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Carl.sh E: Edge data plane — self-hosted Supabase stack (BLOCKING)

1 participant