-
Notifications
You must be signed in to change notification settings - Fork 1
docs: add verified quickstart manifests #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Context: Supabase Operator | ||
|
|
||
| Glossary of domain terms for this repo. Behavior language only, no implementation detail. | ||
|
|
||
| ## Terms | ||
|
|
||
| ### SupabaseProject | ||
| The single CRD of this operator. Namespace scoped. Describes one Supabase instance: which external database and object storage to use, and per component settings. The operator deploys and manages all Supabase components (Kong, Auth, PostgREST, Realtime, Storage API, Meta, Studio) from it. | ||
|
|
||
| ### External dependency | ||
| A service the operator needs but never creates or manages: PostgreSQL and S3 compatible object storage. The user provides both and hands the operator connection credentials through Secrets. The operator only validates and consumes them. | ||
|
|
||
| ### Secret contract | ||
| The exact key names a credentials Secret must contain so the operator can consume it. | ||
| - Database Secret keys: `host`, `port`, `database`, `username`, `password` | ||
| - Storage Secret keys: `endpoint`, `region`, `bucket`, `accessKeyId`, `secretAccessKey` | ||
|
|
||
| ### Quickstart | ||
| The documented golden path for a first time user: install the operator, install external dependencies with well known Helm charts (CloudNativePG for PostgreSQL, MinIO for object storage), create the credential Secrets, apply one SupabaseProject, reach a working Studio via port-forward. Target is a working Studio on a fresh cluster in minutes. | ||
|
|
||
| ### Database initialization | ||
| The one time setup the operator runs against the external PostgreSQL after a project is created: creating the `_supabase` database, Supabase schemas, service roles, and extensions. Requires a superuser grade connection and the `supabase/postgres` image, because Supabase specific extensions must be present. | ||
|
|
||
| ### dev scaffolding | ||
| The manifests under `dev/` used by maintainers for local development. Not user facing, not part of the quickstart. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # ADR 0001: Quickstart uses well known Helm charts, not an operator managed mode | ||
|
|
||
| Date: 2026-07-25 | ||
|
|
||
| Status: accepted | ||
|
|
||
| ## Context | ||
|
|
||
| Issue #18 planned a "managed mode": `spec.database.managed: true` would make the operator provision an in-cluster PostgreSQL StatefulSet, and a similar flag would provision MinIO. The goal was a first working project in under 5 minutes on a bare cluster. | ||
|
|
||
| Building that inside the operator means the operator takes on database lifecycle work: storage, upgrades, credentials, failure recovery. That is a large and permanent maintenance load, and mature tools already do it better. | ||
|
|
||
| A second constraint: the operator only supports the `supabase/postgres` image, because database initialization needs Supabase specific extensions (pgjwt, pg_net and others) and superuser access. Any install path must produce a PostgreSQL running that image. | ||
|
|
||
| ## Decision | ||
|
|
||
| Do not build managed mode. Keep PostgreSQL and S3 strictly user provided. | ||
|
|
||
| Instead, ship a documented quickstart that installs the dependencies with well known Helm charts: | ||
|
|
||
| - PostgreSQL via the CloudNativePG operator, with the cluster image set to `supabase/postgres`. Known required settings: `postgresUID: 101`, `postgresGID: 102` (the image does not use the CNPG default uid 26), and `enableSuperuserAccess: true` (database initialization needs superuser). | ||
| - Object storage via the official MinIO chart (`charts.min.io`), standalone mode, bucket declared through chart values. | ||
|
|
||
| The quickstart manifests live in the repo so users can apply them directly and docs cannot drift from them. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - The operator stays thin: it never owns database or storage lifecycle. | ||
| - The 5 minute goal is met by documentation quality, not new operator code paths. | ||
| - The CNPG plus `supabase/postgres` combination is community proven but not officially supported by either project; the quickstart must be verified end to end whenever images are bumped. | ||
| - Issue #18 Phase A tasks about managed mode are superseded by this decision. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| # Quickstart validation | ||
|
|
||
| This file records a successful run on a fresh kind cluster. | ||
|
|
||
| ## Tested versions | ||
|
|
||
| ```text | ||
| kind v0.32.0 | ||
| Kubernetes v1.36.1 | ||
| CloudNativePG chart 0.29.0 | ||
| CloudNativePG 1.30.0 | ||
| MinIO chart 5.4.0 | ||
| MinIO RELEASE.2024-12-18T13-15-44Z | ||
| cert-manager v1.21.0 | ||
| Supabase PostgreSQL 15.14.1.021 | ||
| Supabase Operator image ghcr.io/strrl/supabase-operator:358f551-dirty | ||
| Supabase Operator chart 0.1.0 | ||
| ``` | ||
|
|
||
| ## Commands | ||
|
|
||
| Create the cluster and add the chart sources. | ||
|
|
||
| ```sh | ||
| kind create cluster --name quickstart-claude --wait 120s | ||
|
|
||
| helm repo add cnpg https://cloudnative-pg.github.io/charts | ||
| helm repo add minio https://charts.min.io/ | ||
| helm repo add jetstack https://charts.jetstack.io | ||
| helm repo update cnpg minio jetstack | ||
| ``` | ||
|
|
||
| Install CloudNativePG and create PostgreSQL. | ||
|
|
||
| ```sh | ||
| helm upgrade --install cnpg cnpg/cloudnative-pg \ | ||
| --kube-context kind-quickstart-claude \ | ||
| --namespace cnpg-system \ | ||
| --create-namespace \ | ||
| --version 0.29.0 \ | ||
| --wait \ | ||
| --timeout 5m | ||
|
|
||
| kubectl --context kind-quickstart-claude \ | ||
| apply -f docs/quickstart/postgres-cluster.yaml | ||
| kubectl --context kind-quickstart-claude \ | ||
| wait --namespace supabase-quickstart \ | ||
| --for=condition=Ready \ | ||
| cluster/supabase-postgres \ | ||
| --timeout 10m | ||
| kubectl --context kind-quickstart-claude \ | ||
| get cluster supabase-postgres \ | ||
| --namespace supabase-quickstart \ | ||
| -o custom-columns='NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status,IMAGE:.spec.imageName,UID:.spec.postgresUID,GID:.spec.postgresGID' | ||
| ``` | ||
|
|
||
| Confirm that PostgreSQL accepts a TLS connection. | ||
|
|
||
| ```sh | ||
| kubectl --context kind-quickstart-claude \ | ||
| run postgres-tls-check \ | ||
| --namespace supabase-quickstart \ | ||
| --image=postgres:15-alpine \ | ||
| --restart=Never \ | ||
| --command \ | ||
| -- sh -c 'PGPASSWORD=quickstart-postgres-password psql "host=supabase-postgres-rw port=5432 dbname=postgres user=postgres sslmode=require" -Atc "select ssl from pg_stat_ssl where pid = pg_backend_pid()"' | ||
| kubectl --context kind-quickstart-claude \ | ||
| wait --namespace supabase-quickstart \ | ||
| --for=jsonpath='{.status.phase}'=Succeeded \ | ||
| pod/postgres-tls-check \ | ||
| --timeout 2m | ||
| kubectl --context kind-quickstart-claude \ | ||
| logs postgres-tls-check \ | ||
| --namespace supabase-quickstart | ||
| ``` | ||
|
|
||
| Install MinIO and confirm the declared bucket. | ||
|
|
||
| ```sh | ||
| helm upgrade --install minio minio/minio \ | ||
| --kube-context kind-quickstart-claude \ | ||
| --namespace supabase-quickstart \ | ||
| --create-namespace \ | ||
| --version 5.4.0 \ | ||
| --values docs/quickstart/minio/values.yaml \ | ||
| --wait \ | ||
| --timeout 5m | ||
| kubectl --context kind-quickstart-claude \ | ||
| rollout status deployment/minio \ | ||
| --namespace supabase-quickstart \ | ||
| --timeout 5m | ||
| kubectl --context kind-quickstart-claude \ | ||
| run minio-check \ | ||
| --namespace supabase-quickstart \ | ||
| --image=quay.io/minio/mc:RELEASE.2024-11-21T17-21-54Z \ | ||
| --restart=Never \ | ||
| --command \ | ||
| -- sh -c 'mc alias set quickstart http://minio:9000 storage-admin quickstart-minio-password >/dev/null && mc stat quickstart/supabase-storage' | ||
| kubectl --context kind-quickstart-claude \ | ||
| wait --namespace supabase-quickstart \ | ||
| --for=jsonpath='{.status.phase}'=Succeeded \ | ||
| pod/minio-check \ | ||
| --timeout 2m | ||
| kubectl --context kind-quickstart-claude \ | ||
| logs minio-check \ | ||
| --namespace supabase-quickstart | ||
| ``` | ||
|
|
||
| Install cert-manager, apply the Secrets, build the operator, and install its | ||
| chart. | ||
|
|
||
| ```sh | ||
| helm upgrade --install cert-manager jetstack/cert-manager \ | ||
| --kube-context kind-quickstart-claude \ | ||
| --namespace cert-manager \ | ||
| --create-namespace \ | ||
| --version v1.21.0 \ | ||
| --set crds.enabled=true \ | ||
| --wait \ | ||
| --timeout 5m | ||
|
|
||
| kubectl --context kind-quickstart-claude \ | ||
| apply -f docs/quickstart/database-secret.yaml | ||
| kubectl --context kind-quickstart-claude \ | ||
| apply -f docs/quickstart/storage-secret.yaml | ||
| kubectl --context kind-quickstart-claude \ | ||
| apply -f docs/quickstart/studio-basic-auth-secret.yaml | ||
|
|
||
| OPERATOR_IMAGE_TAG="$(bash hack/commit-hash.sh)" | ||
| make image | ||
| kind load docker-image \ | ||
| "ghcr.io/strrl/supabase-operator:${OPERATOR_IMAGE_TAG}" \ | ||
| --name quickstart-claude | ||
|
|
||
| helm upgrade --install supabase-operator ./helm/supabase-operator \ | ||
| --kube-context kind-quickstart-claude \ | ||
| --namespace supabase-operator-system \ | ||
| --create-namespace \ | ||
| --set image.repository=ghcr.io/strrl/supabase-operator \ | ||
| --set "image.tag=${OPERATOR_IMAGE_TAG}" \ | ||
| --set image.pullPolicy=IfNotPresent \ | ||
| --wait \ | ||
| --timeout 5m | ||
| ``` | ||
|
|
||
| Apply the project and check every component. | ||
|
|
||
| ```sh | ||
| kubectl --context kind-quickstart-claude \ | ||
| apply -f docs/quickstart/supabase-project.yaml | ||
| kubectl --context kind-quickstart-claude \ | ||
| wait --namespace supabase-quickstart \ | ||
| --for=jsonpath='{.status.phase}'=Running \ | ||
| supabaseproject/quickstart \ | ||
| --timeout 10m | ||
| kubectl --context kind-quickstart-claude \ | ||
| get supabaseproject quickstart \ | ||
| --namespace supabase-quickstart \ | ||
| -o custom-columns='NAME:.metadata.name,PHASE:.status.phase' | ||
| kubectl --context kind-quickstart-claude \ | ||
| get deployment \ | ||
| --namespace supabase-quickstart \ | ||
| -o custom-columns='NAME:.metadata.name,READY:.status.readyReplicas,DESIRED:.spec.replicas' | ||
| ``` | ||
|
|
||
| In one terminal, forward Kong. | ||
|
|
||
| ```sh | ||
| kubectl --context kind-quickstart-claude \ | ||
| port-forward service/quickstart-kong 18000:8000 \ | ||
| --namespace supabase-quickstart | ||
| ``` | ||
|
|
||
| In another terminal, check the unauthenticated and authenticated responses. | ||
|
|
||
| ```sh | ||
| curl \ | ||
| --output /dev/null \ | ||
| --silent \ | ||
| --write-out 'HTTP %{http_code}\n' \ | ||
| http://127.0.0.1:18000/ | ||
| curl \ | ||
| --user supabase:quickstart-studio-password \ | ||
| --location \ | ||
| --output /dev/null \ | ||
| --silent \ | ||
| --show-error \ | ||
| --write-out 'HTTP %{http_code}\n' \ | ||
| http://127.0.0.1:18000/ | ||
| ``` | ||
|
|
||
| ## Selected outputs | ||
|
|
||
| ```text | ||
| CloudNativePG: | ||
| NAME READY IMAGE UID GID | ||
| supabase-postgres True supabase/postgres:15.14.1.021 101 102 | ||
|
|
||
| Database TLS check: | ||
| t | ||
|
|
||
| MinIO: | ||
| Name : supabase-storage | ||
| Type : folder | ||
| Location : us-east-1 | ||
| Objects count: 0 | ||
|
|
||
| SupabaseProject: | ||
| NAME PHASE | ||
| quickstart Running | ||
|
|
||
| Deployments: | ||
| minio 1 1 | ||
| quickstart-auth 1 1 | ||
| quickstart-kong 1 1 | ||
| quickstart-meta 1 1 | ||
| quickstart-postgrest 1 1 | ||
| quickstart-realtime 1 1 | ||
| quickstart-storage 1 1 | ||
| quickstart-studio 1 1 | ||
|
|
||
| Studio through Kong: | ||
| HTTP 401 | ||
| HTTP 200 | ||
| ``` | ||
|
|
||
| ## Static checks | ||
|
|
||
| ```sh | ||
| kubectl --context kind-quickstart-claude \ | ||
| apply --dry-run=client -f docs/quickstart/ | ||
| helm template minio minio/minio \ | ||
| --kube-context kind-quickstart-claude \ | ||
| --namespace supabase-quickstart \ | ||
| --version 5.4.0 \ | ||
| --values docs/quickstart/minio/values.yaml | ||
| helm lint ./helm/supabase-operator | ||
| git diff --check | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: supabase-db-credentials | ||
| namespace: supabase-quickstart | ||
| type: Opaque | ||
| stringData: | ||
| host: supabase-postgres-rw.supabase-quickstart.svc.cluster.local | ||
| port: "5432" | ||
| database: postgres | ||
| username: postgres | ||
| password: quickstart-postgres-password |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| mode: standalone | ||
|
|
||
| rootUser: storage-admin | ||
| rootPassword: quickstart-minio-password | ||
|
|
||
| replicas: 1 | ||
|
|
||
| persistence: | ||
| enabled: true | ||
| size: 1Gi | ||
|
|
||
| resources: | ||
| requests: | ||
| memory: 256Mi | ||
| cpu: 250m | ||
| limits: | ||
| memory: 512Mi | ||
| cpu: 500m | ||
|
|
||
| buckets: | ||
| - name: supabase-storage | ||
| policy: none | ||
| purge: false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| apiVersion: v1 | ||
| kind: Namespace | ||
| metadata: | ||
| name: supabase-quickstart | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: postgres-superuser | ||
| namespace: supabase-quickstart | ||
| type: kubernetes.io/basic-auth | ||
| stringData: | ||
| username: postgres | ||
| password: quickstart-postgres-password | ||
| --- | ||
| apiVersion: postgresql.cnpg.io/v1 | ||
| kind: Cluster | ||
| metadata: | ||
| name: supabase-postgres | ||
| namespace: supabase-quickstart | ||
| spec: | ||
| instances: 1 | ||
| imageName: supabase/postgres:15.14.1.021 | ||
| postgresUID: 101 | ||
| postgresGID: 102 | ||
| enableSuperuserAccess: true | ||
| superuserSecret: | ||
| name: postgres-superuser | ||
| storage: | ||
| size: 1Gi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: supabase-storage-credentials | ||
| namespace: supabase-quickstart | ||
| type: Opaque | ||
| stringData: | ||
| endpoint: http://minio.supabase-quickstart.svc.cluster.local:9000 | ||
| region: us-east-1 | ||
| bucket: supabase-storage | ||
| accessKeyId: storage-admin | ||
| secretAccessKey: quickstart-minio-password |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: supabase-studio-basic-auth | ||
| namespace: supabase-quickstart | ||
| type: Opaque | ||
| stringData: | ||
| username: supabase | ||
| password: quickstart-studio-password |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a fresh cluster or during slow image pulls, this wait can finish before any component pod is ready:
reconcileAllComponentsonly creates/updates the Deployments, andinternal/controller/supabaseproject_controller.go:158-168immediately setsstatus.phasetoRunningwithout checking Deployment availability. The followingkubectl getalso succeeds whenREADYis zero, so the subsequent Kong port-forward can race with startup and make the documented validation intermittently fail; wait for each component Deployment to become Available (or usekubectl rollout status) before testing Studio.Useful? React with 👍 / 👎.