Kubernetes-native ways to run Supabase on your own cluster.
Overview | Quick Start | Helm Chart | Supabase Docs | Contributing
You can choose between two approaches:
- Supabase Kubernetes Operator: manage Supabase through Kubernetes Custom Resources (
core.supabase.io/v1alpha1). The Operator is in an early stage of development and its API may change. - Supabase Helm Chart: deploy Supabase using a traditional Helm chart. See
charts/supabasefor details.
The Operator exposes the following Kubernetes Custom Resources:
| Resource | Short name | Description |
|---|---|---|
Project |
projects |
Represents a complete Supabase instance. It is modular, allowing you to enable only the components you need |
SingleDatabase |
singledatabases |
Postgres database managed by the Operator |
Function |
functions |
Edge Functions deployed in the cluster |
Migration |
migrations |
Applies SQL scripts to referenced databases. Also used internally by the Operator to manage Supabase upgrade migrations |
Before you begin, make sure you have:
- A Kubernetes cluster (1.28+ recommended)
kubectlconfigured to connect to your clusterhelm3.x+make- Docker (or another container runtime supported by the Makefile
CONTAINER_TOOLvariable) - A container registry accessible from your cluster, because you must build and push the Operator image before deploying it
Add the Supabase Helm repository:
helm repo add supabase https://supabase-community.github.io/supabase-kubernetes
helm repo updateThe Operator is not published as a pre-built image, so you must build and push it yourself. Run:
make docker-build IMG=example.com/supabase-operator:v0.0.1
make docker-push IMG=example.com/supabase-operator:v0.0.1Then deploy the Operator into the supabase-operator namespace:
helm install supabase-operator supabase/supabase-operator \
--namespace supabase-operator \
--create-namespace \
--set manager.image.repository=example.com/supabase-operator \
--set manager.image.tag=v0.0.1This installs the CRDs and deploys the controller in a single step.
Create a SingleDatabase resource. The Operator will provision a supabase/postgres StatefulSet, Service, PVC, and a Secret with the generated credentials.
kubectl apply -f - <<EOF
apiVersion: core.supabase.io/v1alpha1
kind: SingleDatabase
metadata:
name: supabase
spec:
storage:
accessModes:
- ReadWriteOnce
size: 20Gi
EOFRetrieve the generated database password:
kubectl get secret supabase-postgres-auth -o go-template='Password: {{.data.password | base64decode}}{{"\n"}}'To reset the database password, delete the Secret. The Operator will recreate it and sync the new password into Postgres:
kubectl delete secret supabase-postgres-authCreate a Project that references the database and enables the components you need.
kubectl apply -f - <<EOF
apiVersion: core.supabase.io/v1alpha1
kind: Project
metadata:
name: supabase
spec:
http:
protocol: "http"
hostname: "api.supabase.local"
databaseRef:
kind: SingleDatabase
name: supabase
envoy:
enable: true
service:
type: LoadBalancer
studio:
enable: true
orgName: "Default Organization"
projName: "Default Project"
storage:
accessModes:
- ReadWriteOnce
size: 1Gi
meta:
enable: true
replicas: 2
auth:
enable: true
siteUrl: "https://myapp.supabase.com"
disableSignup: false
enableEmailSignup: true
enableAnonymousUsers: false
functions:
enable: true
verifyJwt: false
EOFThe Operator will provision Deployments, Services, Secrets, and run sync Jobs to configure JWT keys and the database.
Once the Project is ready, forward the Envoy gateway to your local machine:
kubectl port-forward svc/supabase-envoy 8000:8000The Studio and the Supabase APIs are available at:
http://localhost:8000
Retrieve the dashboard credentials generated by the Operator:
kubectl get secret supabase-envoy-auth -o go-template='Username: {{.data.username | base64decode}}{{"\n"}}Password: {{.data.password | base64decode}}{{"\n"}}'Retrieve the API keys:
kubectl get secret supabase-jwt -o go-template='Publishable Key: {{index .data "publishable-key" | base64decode}}{{"\n"}}Secret Key: {{index .data "secret-key" | base64decode}}{{"\n"}}'To rotate the API keys, delete the JWT Secret. The Operator will regenerate it:
kubectl delete secret supabase-jwtCreate a Function resource that belongs to a Project:
kubectl apply -f - <<'EOF'
apiVersion: core.supabase.io/v1alpha1
kind: Function
metadata:
name: hello
spec:
projectRef: supabase
functionName: hello
source:
index.ts: |
Deno.serve(async (req) => {
const { name = "World" } = await req.json().catch(() => ({}));
return new Response(JSON.stringify({ message: `Hello, ${name}!` }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
});
EOFFunctions are exposed through Envoy at /functions/v1/<function-name>. To test locally:
kubectl port-forward svc/supabase-envoy 8000:8000Then invoke the function:
curl -X POST http://localhost:8000/functions/v1/hello \
-H "Content-Type: application/json" \
-d '{"name":"Supabase"}'Contributions are welcome. Before starting significant work, please open an issue to discuss your idea or bug report. When you are ready, fork the repository, make your changes, and open a pull request.
For setup instructions, build commands, and testing workflows, see DEVELOPERS.md.
This project is supported by the community and not officially supported by Supabase. Please do not create issues on the official Supabase repositories if you face problems using this project. Instead, open an issue on this repository.