Self-hosting

Google Cloud setup

The Google Cloud reference deployment: Cloud Run, Cloud SQL with IAM database auth, Cloud Storage, Secret Manager, an SMTP relay and a Cloud Scheduler OIDC tick, from the Terraform template.

This is the reference deployment on Google Cloud. The template is in deploy/gcp/terraform/, and deploy/gcp/README.md has the full commands. The GCP reference profile runs the same provider combination locally against emulators.

AreaGoogle Cloud serviceSettings
HostingCloud Run service and a Cloud Run migrate job
DatabaseCloud SQL for PostgreSQL 16 with IAM database auth, over the Cloud Run Cloud SQL socketDB_PROVIDER=postgres, DATABASE_AUTH=gcp, DATABASE_URL=postgresql://<sa>%40<project>.iam@/usertasks?host=/cloudsql/<connection>
AuthBuilt-in, plus Google over OIDCAUTH_SSO_PROVIDERS with "preset":"google" and hostedDomain
StorageCloud Storage (public access blocked)STORAGE_PROVIDER=gcs, GCS_PROJECT_ID, STORAGE_BUCKET_MAP
RealtimeBuilt-in SSEREALTIME_PROVIDER=sse
SchedulerCloud Scheduler every minute, with an OIDC tokenSCHEDULER_PROVIDER=external, SCHEDULER_OIDC_SERVICE_ACCOUNTS, SCHEDULER_OIDC_AUDIENCE
EmailWorkspace SMTP relay, or any SMTP relayEMAIL_PROVIDER=smtp, SMTP_*, SMTP_PASSWORD=secret://smtp-password
SecretsSecret Manager (roles/secretmanager.secretAccessor)SECRETS_PROVIDER=gcp_secret_manager, GCP_SECRET_MANAGER_PROJECT, ENCRYPTION_KEY=secret://encryption-key; optionally GCP_SECRET_MANAGER_ENDPOINT for a regional endpoint
Log export (per workspace)Cloud Logging or Pub/Sub destinations, with a service-account keySettings → Log Export; LOG_EXPORT_ALLOW_INSTANCE_IDENTITY=true to let destinations use the service's workload identity (single-tenant only)
KMS (optional)A Cloud KMS key wrapping the data keys (roles/cloudkms.cryptoKeyEncrypterDecrypter)KMS_PROVIDER=gcp_kms, GCP_KMS_KEY_NAME; then usertasks-admin kms rotate and kms rewrap
CacheMemorystore for Redis / Valkey with in-transit encryption (needed with more than one instance)CACHE_PROVIDER=redis, CACHE_REDIS_URL=rediss://<ip>:6378, CACHE_REDIS_TLS_CA_FILE, CACHE_REDIS_PASSWORD (AUTH string) or CACHE_REDIS_AUTH=gcp_iam; or CACHE_PROVIDER=postgres

Steps

  1. Create the infrastructure: terraform apply with deploy_apps=false. That enables the APIs and creates Artifact Registry, Cloud SQL, the buckets and the secrets.
  2. Push the image to Artifact Registry. Build it with --build-arg INCLUDE_OPTIONAL_DB_DRIVERS=true if workflows use the Snowflake, Oracle or MongoDB connectors (Optional drivers).
  3. Grant the IAM database user its privileges. Run the db_grant_sql output once as postgres, for example in Cloud SQL Studio. A new IAM database user has no privileges, so the migrations can't create the API roles without this step.
  4. Create the services: terraform apply with deploy_apps=true. Then run the migrate job: gcloud run jobs execute <prefix>-migrate.
  5. Create the first workspace. Run the migrate job once with overridden arguments (node admin.cjs bootstrap --email … --org …), with the password in BOOTSTRAP_PASSWORD.
  6. Check the install: run node admin.cjs doctor the same way.

Not wired up yet

  • The Cloud SQL Node.js Connector. The app uses Cloud Run's built-in socket instead.

Moving an existing Supabase install

See Switching providers. For the database step, the target role needs cloudsqlsuperuser.