Overview
Supabase is an open-source backend-as-a-service built on PostgreSQL. This template deploys the full self-hosted Supabase stack on Control Plane — all services run in your own GVC with no dependency on Supabase Cloud.Architecture
- Postgres — Supabase-patched PostgreSQL 15 with pgvector, pg_graphql, pg_net, pgjwt, and other required extensions pre-installed.
- Kong — API gateway and single public entry point. Routes all traffic to PostgREST, Auth, Realtime, and Storage.
- PostgREST — Auto-generated REST and GraphQL API derived from your Postgres schema. Stateless, scales horizontally.
- Auth (GoTrue) — Full-featured auth service supporting email/password, magic links, OAuth providers, and JWT sessions. Stateless, scales horizontally.
- Realtime — WebSocket server that streams database change events to subscribed clients. Stateless, scales horizontally.
- Storage — Object storage API backed by S3, GCS, or a local volume.
- Studio — Web dashboard for managing your database, auth users, storage, and API settings.
- pg_meta — Postgres metadata API. Runs as a sidecar inside the Studio workload.
- PgBouncer (optional) — Connection pooler that multiplexes application connections into a smaller pool of real database connections.
- Backup (optional) — Logical (
pg_dumpcron) or WAL-G (continuous WAL archiving with PITR support).
What Gets Created
- Stateful Postgres Workload — Supabase-patched PostgreSQL with a persistent volume set.
- Standard Kong Workload — API gateway, autoscales on RPS.
- Standard PostgREST Workload — REST/GraphQL API, autoscales on RPS.
- Standard Auth Workload — GoTrue auth service, autoscales on RPS.
- Standard Realtime Workload — WebSocket change feed, autoscales on RPS.
- Standard Storage Workload — Object storage API, autoscales on RPS (optional, enabled by default).
- Standard Studio Workload — Web dashboard with pg_meta sidecar (optional, enabled by default).
- Standard PgBouncer Workload — Connection pooler (optional, disabled by default).
- Cron Backup Workload (optional) — Logical or WAL-G backup on a schedule.
- Volume Sets — One for Postgres data; one for Storage when using the
localbackend. - Identity & Policy — Identities bound to each workload with
revealaccess to credential secrets, and cloud storage access when backup or S3/GCS storage is enabled. - Secrets — Dictionary secrets for Postgres credentials, JWT keys, and service API keys; opaque secrets for Kong routing config, SMTP settings, and OAuth provider credentials.
This template does not create a GVC. You must deploy it into an existing GVC.
Prerequisites
This template has no external prerequisites unless S3/GCS storage or backup is enabled. To install, follow the instructions for your preferred method:UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Configuration
The defaultvalues.yaml for this template:
JWT Keys
Supabase uses JWT to authenticate requests between services and from clients.jwt.secret— The signing secret for all JWTs. Must be at least 32 characters.jwt.secretKeyBase— Used by Realtime (Phoenix) for cookie signing. Must be at least 64 characters. Generate withopenssl rand -base64 64.jwt.anonKey— Public key for unauthenticated (anonymous) client access.jwt.serviceRoleKey— Privileged key that bypasses row-level security. For trusted server-side code only.
Kong (API Gateway)
Kong is the single entry point for all Supabase API traffic. PostgREST, Auth, Realtime, and Storage are only reachable through Kong.kong.publicAccess.enabled— Expose Kong on a public external endpoint.kong.publicAccess.siteUrl— The full URL clients will reach Kong at (e.g.https://api.my-app.com). Required whenpublicAccessis enabled. GoTrue uses this for OAuth redirect callbacks and magic link emails.
publicAccess is disabled, internal clients use the Kong hostname within the GVC and OAuth/magic links will not work.
Postgres
postgres.password— Database superuser password. Change before deploying to production.postgres.resources— CPU and memory limits/requests for the Postgres workload.postgres.volumeset.capacity— Initial volume size in GiB (minimum 10). Autoscaling is configurable.postgres.internalAccess.type— Controls which workloads can reach Postgres directly:same-gvc,same-org,workload-list, ornone. All Supabase services connect internally. Useworkload-listto also grant access to your own application workloads.
Auth (GoTrue)
auth.disableSignup— Set totrueto prevent new user registration.
auth.smtp.enabled— Enable SMTP. When disabled, all signups are auto-confirmed and email flows are unavailable.auth.smtp.host/auth.smtp.port— SMTP server address and port.auth.smtp.user/auth.smtp.password— SMTP credentials.auth.smtp.senderName/auth.smtp.senderEmail— Display name and from address for outgoing emails.
auth.providers and adding credentials:
- Authorized JavaScript Origin:
{kong.publicAccess.siteUrl} - Authorized Redirect URI:
{kong.publicAccess.siteUrl}/auth/v1/callback
OAuth requires
kong.publicAccess.enabled: true and a valid siteUrl. OAuth providers will not redirect to internal hostnames.Storage
Three backends are supported:| Backend | Description |
|---|---|
s3 | Stateless, horizontally scalable. Recommended for production. |
gcs | GCS accessed via the S3-compatible API using HMAC keys. No Cloud Account needed. |
local | Stateful, single-replica, volume-backed. For development only. |
s3: set storage.s3.bucket, storage.s3.region, storage.s3.cloudAccountName, and storage.s3.policyName. The IAM policy must grant s3:GetObject, s3:PutObject, and s3:DeleteObject on the bucket.
For gcs: create HMAC keys in the GCP console under Cloud Storage → Settings → Interoperability and set storage.gcs.accessKeyId and storage.gcs.secretAccessKey.
If using S3/GCS for backup as well, storage and backup require separate buckets, cloud accounts, and IAM policies.
Studio (Web Dashboard)
Studio is protected by username and password login and has no external access by default.studio.username/studio.password— Login credentials. Change before deploying to production.studio.allowedCidrs— List of CIDRs allowed to reach Studio externally. Empty by default (no external access). Usecpln workload connectfor local tunnel access, or set to["0.0.0.0/0"]to open it publicly (login is still required).
PgBouncer
PgBouncer multiplexes application connections into a smaller pool of real database connections, reducing Postgres connection overhead under high concurrency. Disabled by default.| Pool Mode | Description |
|---|---|
transaction | Connection held only for the duration of a transaction. Best for most web and API workloads. Not compatible with SET variables, temporary tables, or advisory locks. |
session | Connection held for the entire client session. Compatible with all Postgres features. |
statement | Connection returned after every statement. Transactions not supported. |
pgbouncer.defaultPoolSize— Number of real Postgres connections per pool (default:25).pgbouncer.maxClientConn— Maximum number of client connections PgBouncer accepts (default:1000).
Connecting
All API traffic flows through Kong. Connect your application using the Kong endpoint:| Endpoint | Address |
|---|---|
| API — internal | {release-name}-kong.{gvc}.cpln.local:8000 |
| API — public | {kong.publicAccess.siteUrl} (when publicAccess enabled) |
| Postgres — direct | {release-name}-postgres.{gvc}.cpln.local:5432 |
| Postgres — via PgBouncer | {release-name}-pgbouncer.{gvc}.cpln.local:5432 (when enabled) |
| Service | Path |
|---|---|
| PostgREST (REST API) | /rest/v1/ |
| Auth (GoTrue) | /auth/v1/ |
| Storage | /storage/v1/ |
| Realtime | /realtime/v1/ |
apikey: {anonKey} as a header on all requests. Use serviceRoleKey for privileged server-side calls. The Supabase client library handles auth headers automatically:
Backing Up
Two backup modes are available:| Mode | Mechanism | Best For |
|---|---|---|
logical | pg_dump cron | Portable SQL dumps, smaller databases, cross-version migrations |
walg | Continuous WAL archiving + base backups | Production — supports point-in-time recovery (PITR) |
backup.enabled: true, choose a mode and provider, then fill in the corresponding provider block.
AWS S3
Set up a Cloud Account
If you do not have one, create a Cloud Account. Set
backup.aws.cloudAccountName to its name.GCS
Set up a Cloud Account
If you do not have one, create a Cloud Account. Set
backup.gcp.cloudAccountName to its name.Restoring a Backup
Logical Restore
Run from a machine with network access to Postgres (e.g. viacpln workload connect):
AWS S3:
WAL-G Restore
WAL-G restores require an empty data directory.Create a new volume set
Create a fresh empty volume set for the restore target — do not reuse the existing one.
Run the restore
Run a one-off workload with the new volume set mounted at
/var/lib/postgresql/data and execute:Important Notes
- Use the Supabase Postgres image —
supabase/postgresis required. The standardpostgresimage is missing extensions that GoTrue, PostgREST, Realtime, and Storage depend on. - JWT keys must match —
anonKeyandserviceRoleKeymust be HMAC-SHA256 JWTs signed withjwt.secret. Mismatched keys producebad_jwterrors. Use the official Supabase key generator to produce a matching set. - Change default credentials before production —
jwt.secret,postgres.password, andstudio.passwordare placeholders. Replace all of them before any production deployment. - OAuth requires a public siteUrl — Set
kong.publicAccess.enabled: trueandkong.publicAccess.siteUrlbefore configuring any OAuth provider. - Storage and backup use separate buckets — Do not share a bucket between
storage.s3andbackup.aws. Each requires its own bucket, cloud account, and IAM policy. - Studio has no external access by default — Use
cpln workload connectfor local access, or setstudio.allowedCidrsto open it externally.
External References
Supabase Self-Hosting Guide
Official self-hosting documentation and architecture overview
Supabase Client Libraries
JavaScript, Python, Swift, Kotlin, and other client SDK references
GoTrue (Auth) Documentation
GoTrue auth service configuration and API reference
PostgREST Documentation
Auto-generated REST API from your Postgres schema
WAL-G Documentation
WAL-G continuous archiving and PITR restore documentation
Generate Supabase API Keys
Generate matching JWT secret, anonKey, and serviceRoleKey