Self-hosted service
supabase-community/supabase-kubernetes avatar
supabase-community/supabase-kubernetes

supabase-kubernetes: running Supabase on a cluster you control

Deploy Supabase on Kubernetes

823 stars290 forksGoApache-2.0

At a glance

What is it?
This repository offers two ways to run Supabase on your own Kubernetes cluster, a traditional Helm chart and an operator that exposes each Supabase service as a Custom Resource. The operator is honest about being early stage, and the chart is the more predictable of the two.
Who is it for?
Pick the Helm chart path if you want a predictable deployment you can read values for and update with helm, and pick the operator path only if you want Supabase resources reconciled by a controller and can accept a v1alpha1 API that may change. Do not use this project if you need official support, since it is maintained by the community and explicitly not supported by Supabase.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One repository, two deployment models: a Helm chart and an operator

supabase-kubernetes is a community project for running Supabase on a cluster you control, and the first decision it asks you to make is which of two models you want. The first is a traditional Helm chart, deployed with helm install and configured through values. The second is a Kubernetes operator that manages Supabase through Custom Resources in the API group core.supabase.io/v1alpha1.

The documentation is direct about the maturity gap between them. The operator is described as being in an early stage of development with an API that may change, while the Helm chart is presented as the conventional route with its own README under charts/supabase.

That split is the single most useful thing to know before you start. Both routes are maintained in the same repository, both produce a Supabase deployment on the same cluster, and they are not mutually exclusive in principle, but they are very different in what they ask of you. The chart gives you a rendered manifest set and a values file. The operator gives you a controller that reconciles desired state against what is running.

The support boundary matters too. The project states that it is supported by the community and not officially supported by Supabase, and asks that issues be filed on this repository rather than on the official Supabase ones.

The operator models every Supabase service as its own Custom Resource

The operator's design is visible in the resource table. Twelve resources are exposed, each with a short name and a clear job. A Project holds shared configuration, credentials, migrations and database synchronization. A SingleDatabase is a Postgres database managed by the operator.

Then there is one resource per Supabase component. Auth for Supabase Auth, Rest for PostgREST, Meta for Postgres Meta, Realtime for Supabase Realtime, Storage for Supabase Storage, Studio for Supabase Studio, and Supavisor for the PostgreSQL connection pooler, which the table describes as supporting both session and transaction modes.

Two entries are worth reading twice. Migration applies SQL scripts to referenced databases and is also used internally by the operator to manage Supabase upgrade migrations, so upgrade handling is part of the model rather than an afterthought. EdgeRuntime is described as the Edge Functions runtime with an operator-managed router and import map, which means the operator manages more than a Deployment for that component.

Envoy appears in the same table as the API gateway component, and the Ingress instructions make it a hard requirement rather than an option, with the named port envoy having to survive any Service overrides you make.

Installing the operator brings the CRDs and the controller in a single helm release

The prerequisites are modest and specific: a Kubernetes cluster with 1.28 or newer recommended, kubectl configured against it, and helm 3.x or newer. The documentation also notes that other installation methods exist, among them a Nix route, but the helm path is the one written out in full.

Start by pointing helm at the project's chart repository:

bash
helm repo add supabase https://supabase-community.github.io/supabase-kubernetes
helm repo update

Then install the operator into a namespace of its own:

bash
helm install supabase-operator supabase/supabase-operator \
  --namespace supabase-operator \
  --create-namespace

The value of doing this in one step is the CRDs. The documentation states plainly that this installs the CRDs and deploys the controller in a single step, which removes the usual failure mode of applying resources before their definitions exist. The namespace flag with create-namespace also means the operator does not collide with anything else you run in the cluster.

The underlying binary is built from Go source with controller-runtime, so a failure here is usually a cluster version or RBAC problem rather than a missing dependency.

The supabase-project chart creates the database, the project and the enabled components

With the operator running, the second chart does the actual project setup. The documentation describes it as creating a SingleDatabase, a Project, and the enabled component resources, and the install needs two required values:

bash
helm install supabase supabase/supabase-project \
  --set fullnameOverride=supabase \
  --set project.publicUrl=http://localhost:8000

Once that release is in place, the operator takes over the work. The documentation states that it provisions the Postgres StatefulSet, the component Deployments, Services and Secrets, and runs sync Jobs to configure JWT keys and the database.

The two values carry different weight. The fullnameOverride controls the generated resource names, and it is what makes the later commands work: the secret names, the Envoy service name and the port-forward target all follow from it. The project.publicUrl is the address the deployment believes it is reachable at, which is why the Ingress section later asks you to set it to the matching public URL.

A StatefulSet rather than a Deployment for Postgres is the right call for a database, since it gives the volume a stable identity. It also means pod names are not random, so anything that assumes a random suffix in a resource name will not find the database.

Generated credentials live in three named secrets that you read yourself

A fresh install leaves you without visible passwords or keys, because the operator creates them as Kubernetes Secrets rather than putting them in your values file. The documentation describes a single kubectl command that retrieves the generated database password, the Studio credentials and the API keys.

The secrets involved are named supabase-postgres-auth, supabase-envoy-auth and supabase-jwt. The first holds the database password, the second holds the Studio username and password, and the third holds the publishable key and the secret key. The command prints them by decoding the base64 data field of each secret and labelling the output, which is the standard kubectl idiom for this.

Two details are worth planning around. The keys are generated, so there is no value to put in a Git repository or a Helm values file, and the only copy is what you read out of the cluster. And the JWT secret is used by the operator's sync Jobs to configure the running services, so changing it after the fact is not a matter of editing one secret and moving on. The documentation does not describe a rotation procedure for these generated keys.

Getting traffic in: port-forward for a laptop, Ingress with strict Envoy conditions

For local use, the path is short. Forward the Envoy gateway to your machine and the Studio plus the Supabase APIs are on one port:

bash
kubectl port-forward svc/supabase-envoy 8000:8000

That is why the project.publicUrl value in the install command points at http://localhost:8000. Everything, Studio included, arrives through Envoy rather than through per-component Services, so one forward gives you the whole surface.

For a real deployment, the Ingress route has conditions that are easy to trip over. You set ingress.enable to true and ingress.host, and the Ingress forwards the root path to Envoy while preserving Studio authentication. The cluster has to provide the Ingress Controller and the TLS Secrets itself, since the chart does not create them. Optional className, annotations and tls fields configure the controller and TLS termination.

The strict part is the last sentence of that section: Envoy must be enabled, and Service overrides must preserve its named port envoy. If you override the Envoy Service and change or drop that port name, the Ingress has nothing to target and Studio authentication stops working as documented. This is the failure to check first when an Ingress deployment returns errors.

A Go controller compiled to a distroless image, with the API still at v1alpha1

The implementation is Go, with the module requiring go 1.25.3 and controller-runtime v0.23.3 alongside client-go and the Kubernetes API packages at v0.35.0. Tests use Ginkgo and Gomega, and the JWT handling uses the golang-jwt library. The repository layout follows the usual operator shape, with api/ holding the resource definitions, cmd/ the entry point, internal/ the controller logic and config/ the runtime configuration.

The Dockerfile shows the packaging decisions. A golang builder stage downloads modules first so source changes do not invalidate the dependency layer, then builds with CGO disabled and no fixed GOARCH so the binary matches the platform the build was requested on. The runtime image is distroless static, running as user 65532:65532 with the manager binary copied to the root and /manager as the entry point. A Makefile wraps this with a help target, a manifests target and a build target, and its image reference defaults to a placeholder tag.

Against that, the API group is v1alpha1 and the documentation says the operator is early stage with an API that may change. The project was last pushed on 2026-10-20 and the release naming is inconsistent, with supabase-0.8.0 published on 2026-09-05 alongside v0.1.3 and v0.1.2 from 2026-07-23. The licence is Apache-2.0, which permits commercial use and modification with attribution and notice of changes.

Editorial conclusion

Pick the Helm chart path if you want a predictable deployment you can read values for and update with helm, and pick the operator path only if you want Supabase resources reconciled by a controller and can accept a v1alpha1 API that may change. Do not use this project if you need official support, since it is maintained by the community and explicitly not supported by Supabase. Before deploying, check that your cluster is 1.28 or newer, that helm 3.x is available, and that the Ingress route you plan to use keeps Envoy enabled and preserves its named port envoy.

Frequently asked questions

Do I need the Supabase operator, or is the Helm chart enough?

Both are supported in this repository. The Helm chart deploys Supabase with a traditional chart and values file, while the operator manages Supabase through Custom Resources in the core.supabase.io/v1alpha1 group and is described as being at an early stage with an API that may change.

What do I need before running the supabase-kubernetes quick start?

A Kubernetes cluster with 1.28 or newer recommended, kubectl configured to connect to it, and helm 3.x or newer. The install also needs the chart repository added with helm repo add before the operator and project charts can be installed.

Where do I find the database password and API keys after installing?

They are generated as Kubernetes Secrets, not set by you. The documented kubectl command reads the supabase-postgres-auth, supabase-envoy-auth and supabase-jwt secrets and prints the database password, the Studio username and password, the publishable key and the secret key.

Is this project supported by Supabase?

No. The project states that it is supported by the community and not officially supported by Supabase, and asks that issues be opened on this repository instead of on the official Supabase repositories.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. supabase-community/supabase-kubernetes on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/supabase-community-supabase-kubernetes.svg)](https://hysenlabs.com/projects/supabase-community-supabase-kubernetes)

Was this useful?