Deploying Self-Hosted Supabase on Google Cloud: A Complete Guide

Deploy self-hosted Supabase on Google Cloud Compute Engine: VM sizing, firewall rules, Docker setup, SSL, and backups—with real costs and honest trade-offs.

Cover Image for Deploying Self-Hosted Supabase on Google Cloud: A Complete Guide

Google Cloud rarely tops the list when self-hosters compare providers—it lost the price war to Hetzner and the mindshare war to AWS, which is why it didn't headline our best VPS providers for self-hosted Supabase roundup. But plenty of teams end up on GCP anyway: your company already runs there, your credits live there, or you want BigQuery, Cloud DNS, and IAM in the same console as your database.

If that's you, this guide walks through a complete production deployment of self-hosted Supabase on a Compute Engine VM—sizing, firewall rules, Docker, SSL, and backups—along with the GCP-specific costs and quirks that catch people off guard, and an honest look at when GCP is the wrong choice.

Why (and Why Not) Google Cloud

The case for GCP is straightforward if you're already in the ecosystem:

  • One bill, one IAM. Service accounts, audit logs, and org policies apply to your Supabase VM like everything else. For teams with compliance requirements, that consolidation matters.
  • Solid infrastructure primitives. Persistent disks are network-attached, independently snapshottable, and resizable online. Live migration means Google patches host machines without rebooting your VM—a genuine advantage over providers where maintenance means downtime.
  • Committed use discounts. On-demand pricing stings, but a 1-year commitment cuts compute costs by roughly 37%, and 3-year commitments by around 55%.

The case against is mostly money:

  • Compute costs 3–6x more than budget providers. An e2-standard-2 (2 vCPU, 8 GB) runs about $49/month on demand in us-central1. Hetzner sells comparable specs for under €15.
  • Egress fees. Internet egress on the premium network tier is roughly $0.12/GB in North America (standard tier is cheaper, around $0.085/GB), with only a sliver free each month. Hetzner includes 20 TB. If your API serves large files to end users, this line item can eclipse the VM itself—we broke down this math in our true cost of self-hosting Supabase analysis.
  • The free tier won't fit. GCP's always-free e2-micro (1 GB shared-core, select US regions) is far below the requirements of the full Supabase stack. If free-tier hosting is the goal, Oracle Cloud's free tier is the realistic option.

Sizing Your VM

The self-hosted stack runs a dozen containers—Postgres, GoTrue, PostgREST, Realtime, Storage, the API gateway, Studio, and supporting services—and idles around 2.5–3 GB of RAM. Our system requirements guide has full details; here's the Compute Engine cheat sheet:

Use caseMachine typeSpecs~On-demand price (us-central1)
Dev / hobbye2-medium2 vCPU (shared), 4 GB~$25/mo
Small productione2-standard-22 vCPU, 8 GB~$49/mo
Productione2-standard-44 vCPU, 16 GB~$98/mo

Notes: E2 machine types don't receive sustained-use discounts (their base price is already lower), so committed use is how you actually save. Avoid Spot VMs for anything holding your database—they can be preempted with 30 seconds' notice. For the boot disk, pd-balanced at $0.10/GB/month is the right default; pd-ssd ($0.17/GB) only pays off under heavy sustained IOPS.

Step 1: Create the VM and Lock Down the Firewall

Create an Ubuntu 24.04 instance with a network tag we'll use for firewall targeting:

gcloud compute instances create supabase-prod \
  --zone=us-central1-a \
  --machine-type=e2-standard-2 \
  --image-family=ubuntu-2404-lts-amd64 \
  --image-project=ubuntu-os-cloud \
  --boot-disk-size=60GB \
  --boot-disk-type=pd-balanced \
  --tags=supabase

GCP's default VPC ships with a default-allow-ssh rule open to the entire internet. Tighten it. Allow HTTP/HTTPS publicly, and route SSH through Identity-Aware Proxy instead of exposing port 22:

gcloud compute firewall-rules create supabase-allow-web \
  --allow=tcp:80,tcp:443 --target-tags=supabase

gcloud compute firewall-rules create supabase-allow-ssh-iap \
  --allow=tcp:22 --source-ranges=35.235.240.0/20 --target-tags=supabase

The 35.235.240.0/20 range is Google's IAP egress block—SSH now only works via gcloud compute ssh supabase-prod --tunnel-through-iap, authenticated against your Google identity. Critically, nothing opens ports 5432 or 8000. Automated scanners find exposed Postgres ports within hours of a VM going live. If you need direct database access from your laptop, tunnel over IAP or use a mesh VPN like Tailscale.

Step 2: Install Docker and Fetch Supabase

SSH in and install Docker from the official repository:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

Then pull the official Docker setup:

git clone --depth 1 https://github.com/supabase/supabase
mkdir supabase-project
cp -r supabase/docker/* supabase-project/
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project

Step 3: Replace Every Default Secret

The .env.example ships with publicly known credentials—the same POSTGRES_PASSWORD and JWT_SECRET as every other unconfigured deployment on the internet. Replace all of them:

openssl rand -base64 32   # POSTGRES_PASSWORD
openssl rand -base64 32   # JWT_SECRET (min 32 chars)

You'll also need to mint ANON_KEY and SERVICE_ROLE_KEY JWTs signed with your new JWT_SECRET, set DASHBOARD_USERNAME/DASHBOARD_PASSWORD for Studio, and point SITE_URL and API_EXTERNAL_URL at your real domain. Note that since the July 2026 configuration change, API_EXTERNAL_URL conventions shifted for auth paths—our environment variables guide covers how these values interact and the mistakes that produce broken email links and redirect loops.

Once configured:

docker compose pull
docker compose up -d

Step 4: DNS, Reverse Proxy, and SSL

Point an A record at the VM's external IP (consider reserving a static external IP first—ephemeral IPs change on stop/start, and the static reservation costs a few dollars a month). Then put a TLS-terminating reverse proxy in front of the stack. Caddy is the least-effort option:

api.yourdomain.com {
    reverse_proxy localhost:8000
}

Caddy handles Let's Encrypt issuance and renewal automatically. One 2026-specific caveat: the self-hosted stack's default API gateway migrated from Kong to Envoy in August, which changed how custom gateway configuration and the built-in HTTPS listener work. If you're carrying over a customized kong.yml from an older deployment, read our Kong-to-Envoy migration prep guide before upgrading.

Step 5: Backups—Snapshots Are Not Enough

GCP makes disk snapshots easy, and you should use them. Attach a snapshot schedule to the boot disk:

gcloud compute resource-policies create snapshot-schedule supabase-daily \
  --region=us-central1 --max-retention-days=14 \
  --daily-schedule --start-time=04:00

gcloud compute disks add-resource-policies supabase-prod \
  --zone=us-central1-a --resource-policies=supabase-daily

But be clear about what a snapshot is: a crash-consistent image of the whole disk. It restores everything or nothing, to the snapshot's timestamp, on GCP infrastructure only. It won't recover a single table someone dropped at 3 PM, and it ties your disaster recovery to the same provider whose account lockout might be the disaster.

Proper database-level backups—logical dumps or WAL archiving shipped to object storage—belong alongside snapshots, not instead of them. Google Cloud Storage works as a target via its S3-interoperability mode: generate HMAC keys and any S3-compatible tooling can write to storage.googleapis.com. Supascale's automated backups use exactly this approach—scheduled, verified backups to any S3-compatible storage including GCS, with one-click restore. And don't forget that database backups don't include uploaded files; storage backup is its own problem.

What GCP Doesn't Solve

Compute Engine gives you a reliable VM. It gives you nothing for the ongoing operational work of running Supabase on it: minting JWTs by hand, configuring OAuth providers by editing environment variables, tracking upstream breaking changes (the October 2026 Data API grants change is the next one that will bite unprepared self-hosters), and repeating all of it for every project you deploy.

That operational layer is what Supascale adds on top of any VM, GCP included: deploy multiple Supabase projects on one server, configure OAuth providers through a UI instead of env files, bind custom domains with automatic SSL, and schedule S3 backups with one-click restore. It's a one-time license starting at $99 with unlimited projects—no per-server or per-project fees—so it doesn't reintroduce the recurring costs you left Supabase Cloud to escape.

Conclusion

GCP is a legitimate home for self-hosted Supabase when you're already in the ecosystem: the primitives are excellent, live migration and snapshot schedules are real operational wins, and committed-use discounts narrow the price gap. Go in with eyes open about egress fees, skip the undersized free tier, route SSH through IAP, keep 5432 off the internet, and layer database-level backups on top of disk snapshots. And if you're purely price-shopping with no GCP ties, Hetzner still wins on raw economics.

Further Reading