Skip to main content

Supabase Docker Compose: Self-Host the Full Stack (2026)

To self-host Supabase with Docker Compose, clone github.com/supabase/supabase, cd supabase/docker, copy .env.example to .env, replace POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY and SERVICE_ROLE_KEY, then run docker compose up -d. That brings up all seven services — Postgres, GoTrue, PostgREST, Realtime, Storage, Studio and the Kong gateway. Studio lands on http://localhost:3000 and every API call goes through http://localhost:8000.

Supabase is an open-source Firebase alternative. Their cloud offering is excellent, but the whole stack ships as a Compose file, so you can run it locally, on a VPS, or in an air-gapped network and keep full control over your data. If you are still deciding whether you need the whole stack, read Self-Host Postgres or Use Supabase? first — this page is the how, that one is the whether.

Prerequisites

  • Docker and Docker Compose installed (see our installation guide).
  • Git installed.
  • About 4 GB of free RAM. The full stack runs seven containers; it will start on 2 GB but Studio and Realtime get slow.

Step 1: Clone the Supabase Repo

Supabase provides a pre-configured Docker setup in their official repository.

# Get the code
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker

Step 2: Configure Environment Variables

Copy the example environment file:

cp .env.example .env

Now, open .env in your text editor. This file controls everything.

Key Variables to Change

  1. POSTGRES_PASSWORD: The password for the postgres user. Change this immediately if deploying to a public server.
  2. JWT_SECRET: Used to sign authentication tokens. Generate a strong, random string.
  3. ANON_KEY and SERVICE_ROLE_KEY: These are JWTs derived from your JWT_SECRET. You must generate new ones if you change the secret. You can use the Supabase CLI or an online JWT tool to generate these (ensure you use the correct payload structure).
  4. DASHBOARD_USERNAME / DASHBOARD_PASSWORD: Credentials for the Supabase Studio UI.

Step 3: Start the Stack

Run Docker Compose to pull the images and start the services.

docker compose pull
docker compose up -d

This will start a suite of services:

  • Postgres: The core database.
  • GoTrue: Authentication API.
  • PostgREST: Auto-generated REST API.
  • Realtime: WebSocket server.
  • Storage: File storage API.
  • Studio: The dashboard UI.
  • Kong: API Gateway.

Step 4: Accessing Supabase

Once everything is running (check with docker compose ps), you can access the services:

  • Supabase Studio (UI): http://localhost:3000 (Default login: supabase / this_password_is_insecure_and_should_be_updated)
  • API Gateway: http://localhost:8000
  • Postgres Database: localhost:5432

Enabling Analytics (Optional)

The default setup might not include the analytics container (Logflare) enabled by default to save resources. Check the docker-compose.yml file and uncomment the analytics services if you need them.

Data Persistence

The docker-compose.yml uses named volumes to persist data.

  • db-data: Postgres data.
  • storage-data: File uploads.

If you restart the containers, your data remains safe. To wipe everything and start fresh:

docker compose down -v

Running Supabase on a VPS instead of localhost

The defaults in .env all point at localhost, so Studio and the client libraries break the moment you open the stack to a domain. Change these three before you expose anything:

  • SITE_URL — the URL of your own app, used for auth redirects.
  • API_EXTERNAL_URL — the public URL of the Kong gateway, e.g. https://api.example.com.
  • SUPABASE_PUBLIC_URL — the public URL Studio uses to talk to the API.

Kong listens on 8000 over plain HTTP, so put a reverse proxy in front of it for TLS. Caddy is the shortest route — see our Caddy guide — and never publish port 5432 or the Studio port 3000 to the internet.

Updating self-hosted Supabase

The Compose file pins image tags, so an update means pulling the new repo state and the new images:

cd supabase/docker
git pull
docker compose pull
docker compose up -d

Your data lives in named volumes, so it survives the restart. Back up first anyway — docker compose exec db pg_dumpall -U postgres > backup.sql takes a few seconds and has saved plenty of weekends.

Frequently asked questions

How do I self-host Supabase with Docker Compose?

Clone github.com/supabase/supabase, cd into supabase/docker, copy .env.example to .env, change POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, DASHBOARD_USERNAME and DASHBOARD_PASSWORD, then run 'docker compose pull' and 'docker compose up -d'. All seven services start together and Studio is reachable on port 3000.

What ports does self-hosted Supabase use?

Studio runs on port 3000, the Kong API gateway on port 8000, and Postgres on port 5432. Client libraries should only ever talk to port 8000; 3000 and 5432 should stay on the private network or behind a firewall.

Do I have to regenerate ANON_KEY and SERVICE_ROLE_KEY?

Yes, if you change JWT_SECRET. Both keys are JWTs signed with JWT_SECRET, so the defaults stop validating the moment you replace the secret. Generate a new pair with the Supabase CLI or any JWT tool, using the same payload structure ({"role": "anon"} and {"role": "service_role"}) and a matching expiry.

How do I set up secure JWT authentication for self-hosted Supabase Studio?

Studio itself is protected by basic auth through Kong, set by DASHBOARD_USERNAME and DASHBOARD_PASSWORD in .env. The API keys are separate: set a long random JWT_SECRET, regenerate ANON_KEY and SERVICE_ROLE_KEY from it, and never ship SERVICE_ROLE_KEY to a browser — it bypasses row level security.

How much RAM does self-hosted Supabase need?

Plan for 4 GB. The stack runs seven containers (Postgres, GoTrue, PostgREST, Realtime, Storage, Studio, Kong) plus optional analytics. It boots on 2 GB, but Studio and Realtime become noticeably slow and the analytics container will not fit.

Can I run only the Postgres part of Supabase?

Yes. If you only want the database, run plain Postgres instead of the Supabase stack — you drop six containers and the key management that goes with them. You lose the auto-generated REST API, auth, storage and Studio.

How do I update a self-hosted Supabase instance?

Run 'git pull' in the supabase repo, then 'docker compose pull' and 'docker compose up -d' in the docker directory. Named volumes keep your data across the restart. Take a pg_dumpall backup before every update.

Is self-hosted Supabase free?

The software is free and open source under Apache 2.0, so there is no licence cost. You still pay for whatever runs it: a VPS with 4 GB of RAM, storage for the volumes, and your own time for backups, updates and TLS.

Skip the seven containers

If what you actually need is a managed Postgres and a place to run your app, Hostim.dev gives you both without the Compose file.

Deploy on Hostim