Supabase on Kubernetes
Supabase on Kubernetes
Section titled “Supabase on Kubernetes”Architecture authority: ADR 0018.
Selected path
Section titled “Selected path”Reviewed 2026-07-14. Supabase officially recommends Docker for self-hosting and
lists Kubernetes options as community-driven. FractalOps therefore consumes the
community Helm chart directly; it does not fork the chart or add a Supabase
operator. assembly.manifest.json is the current chart, source-commit, archive-digest,
and component-image SSOT. Every Git revision is immutable, while the
supabase-stable-channel.yml workflow checks the upstream non-prerelease channel every
six hours, resolves every enabled image digest, and advances the SSOT only after tests
and a live Kubernetes API dry-run.
The sole Argo CD Application is supabase; its environment overlay renders one Helm
release with Studio and every enabled API component. The former in-repository Supabase,
Storage, and Realtime charts are deleted.
The repository’s operator is explicitly early-stage and has no published image. Adopting it would add an unstable CRD and a locally built controller without removing a required capability, so the standard Helm path is the smaller and more portable choice.
Native capability boundary
Section titled “Native capability boundary”- The chart owns Supabase Deployments, Services, component environment wiring, native secret references, Studio, Auth, PostgREST, Realtime, Storage, postgres-meta, and the internal Kong API gateway.
- CloudNativePG owns PostgreSQL lifecycle and login roles. Backend Git migrations own schemas, grants, RLS, and data repair. External Secrets projects OpenBao values into standard Kubernetes Secrets.
- SeaweedFS provides the S3-compatible durable Storage backend. The chart’s embedded PostgreSQL, MinIO, and application PVCs remain disabled.
- The
object-storagenamespace is the durable SeaweedFS authority. Supabase uses its bucket-scopedSUPABASE_STORAGE_*identity; the legacyseaweedfsnamespace and evidence-writer credentials are not valid runtime targets. - Cluster ingress is composed in the same Application. Kong remains internal because the official self-host topology uses it for API routing and authentication plugins; cluster routing must not reimplement that policy.
In-place manual rollout
Section titled “In-place manual rollout”platform/k8s/argocd/runtime/resources/supabase.application.yaml keeps the live
Application identity and points it at
platform/k8s/environments/lxc-pve-lab/supabase. It has no automated sync policy.
platform/k8s/bootstrap_supabase.sh seeds runtime secrets, waits for the native
ExternalSecret, and publishes this one Application; it does not synchronize it.
- Prove the CNPG backup, migration ledger, worker capacity, SeaweedFS bucket, immutable images, Realtime tenant prerequisites, and rollback pin.
- Preserve the previous Storage data volume as a read-only migration source and
remove its Argo ownership once. First compare
storage.objectswith the volume. When metadata owns objects, migrate through the Storage API. When metadata is empty, archive the orphan bytes witharchive-storage-orphans.job.yaml; it mounts the source read-only and requires count, byte-total, and authenticated SeaweedFS readback equality. Keep the source PVC until restore proof passes. - Manually synchronize
supabase. Normal server-side apply creates the upstream release and foreground pruning removes resources absent from the new source. - Prove Auth, REST, Realtime, and Storage through
supabase.yamon.io; prove Studio throughstudio.yamon.io. Confirm/and/pg/are not public API routes.
The API Ingress exposes only enabled routes declared by upstream Kong: /auth/v1,
/rest/v1, /realtime/v1, /storage/v1, and OAuth discovery.
Studio’s Kong / fallback and postgres-meta /pg/ remain private.
The Storage orphan operation is a one-time live handoff, not desired state. Never add
permanent Argo Force=true or Replace=true annotations to the Application or its
resources.
Version traps
Section titled “Version traps”0.7.1changes component environment values to Kubernetes-native arrays. Values written for0.6.xdo not render correctly and must not be reused.- The chart supplies one database password to component roles such as
supabase_admin,supabase_auth_admin,authenticator, andsupabase_storage_admin; CNPG must reconcile those roles to the same referenced password before rollout. - Realtime requires
_realtimebefore its release migration and arealtimetenant schema. Its generic/healthcheckcan return success while tenant migrations failed; readiness proof must inspect/api/tenants/fractalops-live/healthand requiredata.healthy=true. PreserveSELF_HOST_TENANT_NAME=fractalops-live; upstream seeds use that value asexternal_id, so changing it creates a different tenant instead of adopting the existing native control row. - The chart’s embedded database and MinIO defaults are not production authority in this deployment. A values reset must not silently re-enable them.
- Storage
v1.48.10andv1.60.4use the sameTenantLocationkey shape:<tenant>/<bucket>/<versioned-object>. KeepTENANT_ID=storage-single-tenantacross the file-to-S3 cutover; changing it silently relocates every object. - Standard CNPG PostgreSQL lacks
pg_graphql. PostgREST therefore exposes only migration-ownedpublic,storage;/graphql/v1remains closed. Enable GraphQL only after a CNPG-compatible immutable image provides the extension and a Backend migration ownsgraphql_public.
Verification
Section titled “Verification”uv run --frozen --group test python scripts/update-supabase-stable.py --dry-runkustomize build --enable-helm \ platform/k8s/environments/lxc-pve-lab/supabase >/tmp/supabase-rendered.yamluv run pytest -q \ platform/k8s/composition/supabase/supabase_upstream_contract_test.py \ platform/k8s/cue_generate_native_values_test.py \ platform/k8s/openbao_bootstrap_test.pyplatform/k8s/bootstrap_supabase.shThe bootstrap command mutates OpenBao projections and publishes the Application, so run it only from an authorized operator environment. It intentionally leaves sync manual.
Authoritative references: Supabase self-hosting, official Docker topology, community Kubernetes repository, chart releases, Storage v1.48.10 locator, Storage v1.60.4 locator, and Realtime v2.102.3 release entrypoint.