Skip to content

How to Deploy Supabase on a VPS

Updated Aug 2026

We earn commissions when you shop through the links below. Full disclosure →

Self-host Supabase — the open-source Firebase alternative bundling Postgres, auth, realtime, storage, and edge functions behind one API gateway — on your own VPS with Docker Compose.

Before you start
  • A VPS with at least 4 GB RAM — Supabase is a dozen-container stack, and Postgres, Realtime, and Studio all want memory
  • A fresh Ubuntu server with root/sudo SSH access, Docker + Compose installed
  • openssl on the server (present on stock Ubuntu) — the secret-generation step uses it
  • A domain pointed at the server if you plan to expose the API or Studio over HTTPS — strongly recommended before anything real touches this box
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What self-hosted Supabase actually is

Supabase is not one application — it's a coordinated stack of services behind a single API gateway, and self-hosting it means running all of them yourself via one Docker Compose file: Postgres (the actual database), PostgREST (the auto-generated REST API), GoTrue (auth — the compose service is just called auth), Realtime (database change broadcasts over websockets), Storage (file uploads, with imgproxy for image transforms), Studio (the dashboard), postgres-meta (the database-management API Studio uses), an Edge Functions runtime, Supavisor (connection pooling), and the API gateway itself that fronts everything on one port. That's roughly a dozen containers for one "app" — worth knowing before you commit.

Should you self-host Supabase?

Honest answer: often no. Supabase's hosted free tier covers a lot of hobby projects, and the thing you give up by self-hosting is substantial — on your own box there is no branching, no managed backups or point-in-time recovery, no advanced metrics beyond logs, no ETL, and no platform management API, and the stack runs as a single project (no organizations, no multi-project dashboard). Upgrades, security patching, disaster recovery, and uptime are entirely yours.

Self-hosting earns its keep when the data must stay on your infrastructure (compliance, region, policy), when you're past the free tier and a single VPS beats usage-based pricing, or when you want Postgres you can actually reach as a superuser. If none of those apply, the hosted platform is the pragmatic choice.

Server sizing

Treat 4 GB RAM as the floor — the minimum for the full stack to boot and stay up, not a comfortable number. Postgres, Realtime (an Elixir service), and Studio are each individually hungry, and a dozen containers add up. 8 GB is the sensible starting point for real traffic, and give the disk room to grow — the database and uploaded files both live on this box now. See Best VPS for self-hosting for the ranked picks.

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Supabase

This guide assumes a box prepared per Docker & Compose on Ubuntu. The setup is a sequence of shell commands rather than a compose file you write yourself — the project ships the compose file and you copy it out of the repository. Clone it (shallow — you only need the current state) and copy the docker/ directory into a clean project folder, including the environment template:

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

Stop here. Do not run docker compose up yet — the .env you just copied is full of published placeholder secrets, and the next section replaces them first.

Secrets before first boot — not optional

The .env.example file says it in capitals: you must change all the default values before starting the containers for the first time. The defaults are not weak passwords — they are public knowledge, printed verbatim in the repository and its documentation, including working sample JWTs. A Supabase stack booted with default keys and reachable from the internet is an open database with a friendly dashboard.

The variables that must change, exactly as named in .env:

  • POSTGRES_PASSWORD — the database superuser password.
  • JWT_SECRET — signs every auth token; anyone holding it can mint valid tokens.
  • ANON_KEY and SERVICE_ROLE_KEY — the client-side and server-side API keys. These are JWTs signed by JWT_SECRET, so they must be regenerated together with it — you can't change one and keep the others.
  • DASHBOARD_USERNAME and DASHBOARD_PASSWORD — Studio sits behind HTTP basic auth using these; the defaults are supabase / a published placeholder.
  • SECRET_KEY_BASE and VAULT_ENC_KEY — internal signing and encryption keys with published defaults.

The repository ships a generator that handles the fiddly part (the JWT-signed API keys). It's in the utils/ folder you already copied:

sh utils/generate-keys.sh --update-env

That generates fresh values for JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, VAULT_ENC_KEY, POSTGRES_PASSWORD, DASHBOARD_PASSWORD, and the rest of the secret family, and writes them into .env (keeping a .env.old backup). Set DASHBOARD_USERNAME yourself — the generator leaves it at supabase. Copy the printed ANON_KEY and SERVICE_ROLE_KEY somewhere safe; your client apps need the anon key, and the service-role key belongs only on trusted servers.

Also set the URL variables to match how the stack will actually be reached — SITE_URL, API_EXTERNAL_URL, and SUPABASE_PUBLIC_URL all default to localhost.

Now boot it:

docker compose pull
docker compose up -d  #  →  http://SERVER_IP:8000 (Studio via the API gateway)

The pull fetches a dozen images, so the first run takes a while. When it settles, docker compose ps should show every service running or healthy, and the whole stack answers on port 8000 — the API gateway fronts both the APIs and Studio there (the default Envoy gateway serves plain HTTP only — the optional Kong override adds an HTTPS listener on 8443; the pooler exposes Postgres on 5432 for session mode and 6543 for transaction mode). Log into Studio at http://SERVER_IP:8000 with your DASHBOARD_USERNAME / DASHBOARD_PASSWORD.

Exposing Studio and the API safely

Port 8000 speaks plain HTTP. Basic auth on Studio is the only thing between the internet and your dashboard, and credentials over HTTP are readable in transit — Supabase's own docs tell you to put a reverse proxy with a real TLS certificate in front of the gateway for production, and OAuth logins outright require HTTPS.

Put Caddy in front: proxy your domain to localhost:8000, let Caddy handle certificates, and firewall port 8000 so only localhost reaches the gateway directly. Then update SITE_URL, API_EXTERNAL_URL, and SUPABASE_PUBLIC_URL in .env to the HTTPS domain and restart the stack — env changes only apply on restart. If only you need Studio, consider not publishing it at all and reaching port 8000 over an SSH tunnel or VPN instead; the API is what your apps need public, not the dashboard.

Backups

Everything that matters lives in two places under your project folder:

  • volumes/db/data — the Postgres data directory. Back it up logically with pg_dump against the running database (via the pooler on port 5432, or docker compose exec db pg_dump) on a schedule, and ship the dumps off the box.
  • volumes/storage — the actual uploaded files from the Storage service. A database dump does not include these; the Storage API keeps metadata in Postgres but the bytes are on disk here. Rsync or archive this directory alongside the dumps.

A backup that lives only on the same VPS dies with the VPS. Off-box, scheduled, and restore-tested — otherwise it's a guess, and unlike the hosted platform there is no point-in-time recovery to fall back on.

What breaks compared to the cloud platform

  • No automatic upgrades. Nothing updates itself. Moving to newer service images and applying migrations is a manual, read-the-release-notes affair — take a backup first, every time.
  • Missing platform features. Branching, managed backups and PITR, advanced metrics beyond logs, ETL, analytics and vector buckets, and the platform management API are hosted-platform features that don't exist here.
  • One project per stack. The self-hosted dashboard manages a single project — no organizations, no spinning up a second project next to the first. Want another? That's another compose stack.
  • All operations are yours. Monitoring, disaster recovery, scaling, OS patching — the parts of the hosted bill you stopped paying are now paid in your time.

You're done when docker compose ps shows the stack healthy, Studio loads over HTTPS behind your proxy with the credentials you set, a test table created in Studio is readable through the REST API with your regenerated anon key, and a backup of both the database and volumes/storage exists somewhere that isn't this server.

Next steps

How to self-host Supabase →More self-hosted backend & baas tools →Best VPS for Supabase →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.