Supabase offers an incredible open-source Backend-as-a-Service experience, rivaling Firebase with its powerful suite of tools: Postgres, Auth, Storage, Realtime, and Edge Functions. While the managed cloud platform is excellent, many developers seek greater control, offline capabilities, or specific hosting requirements.
This guide covers two key ways to run Supabase outside the official cloud:
- Local Development: Using the Supabase CLI for rapid iteration, offline work, and cost-free experimentation on your local machine.
- Self-Hosting: Deploying a persistent Supabase instance using Docker on your own infrastructure (VPS, server, etc.) for complete control and customization.
Part 1: Rapid Local Development with the Supabase CLI
This is the quickest way to get a Supabase environment running for development purposes. The CLI manages a temporary Docker setup for you.
Why Use the CLI for Local Dev?
- Offline Capable: Code anywhere, anytime.
- Cost-Free: Experiment without usage limits.
- Fast Iteration: Near-zero latency.
- Safe Testing: Break things without affecting production.
Prerequisites:
- Docker: Install Docker Desktop and ensure it's running.
- Git: Install Git.
- Supabase CLI: The command-line tool to manage the local instance.
Step 1: Install the Supabase CLI
Choose your preferred method:
- npm:
npm install supabase --save-dev
(or usenpx supabase ...
) - Homebrew (macOS/Linux):
brew install supabase/tap/supabase
- Scoop (Windows):
scoop bucket add supabase ...
&&scoop install supabase
- Binaries (Linux): Download from CLI releases.
Verify with: supabase --version
Step 2: Initialize Your Project
In your project's root directory:
supabase init
This creates a supabase folder for configuration and migrations.
Step 3: Start the Local Supabase Stack
supabase start
This downloads Docker images (first time takes longer) and starts all Supabase services. Note the output:
Started Supabase local development setup.API URL: http://localhost:54321GraphQL URL: http://localhost:54321/graphql/v1DB URL: postgresql://postgres:postgres@localhost:54322/postgresStudio URL: http://localhost:54323 # <-- Access the dashboard here!Inbucket URL: http://localhost:54324 # <-- Local email testing!JWT secret: super-secret-jwt-token...anon key: eyJh... (Use this in your frontend)service_role key: eyJh... (Keep this secret, use server-side)
Step 4: Connect and Develop
- Access the local Supabase Studio via the Studio URL.
- Configure your app's Supabase client (supabase-js, etc.) using the local API URL and anon key.
- Use the Inbucket URL to view emails sent by Supabase Auth locally (password resets, confirmations) without needing a real SMTP server for basic testing.
Managing the Local Instance:
supabase status
: Check running services.supabase stop
: Stop services (data persists by default).supabase stop --no-backup
: Stop and delete database data for a clean reset.supabase logs
: View container logs for debugging.supabase db diff
,supabase db reset
: Manage database migrations (essential!).
This CLI setup is fantastic for development, but it's not intended for persistent production use. For that, we need self-hosting.
Part 2: Self-Hosting Supabase with Docker for Production & Control
When you need a stable, persistent Supabase instance on your own infrastructure, potentially for production, staging, or a shared development environment, self-hosting using the official supabase/docker repository is the way to go.
Why Self-Host?
- Full Control: You manage the infrastructure, data, and configuration.
- Data Residency: Keep your data within specific geographical boundaries.
- Customization: Modify configurations, extend with other services.
- Potential Cost Savings: Can be cheaper than the managed service at scale, if you factor in your operational overhead.
- Air-gapped Environments: Run Supabase entirely offline if needed.
Important Considerations (The Trade-offs):
- Maintenance Burden: You are responsible for updates, security patches, monitoring, and troubleshooting.
- Backups: YOU MUST implement your own robust backup strategy for the Postgres database and Storage volumes. Supabase does not manage this for you in a self-hosted setup.
- Security: You are responsible for securing the server, Docker, network access (firewalls), and managing secrets.
- Resource Requirements: Needs a server (VPS, bare metal) with sufficient RAM (8GB+ recommended for moderate use), CPU, and disk space.
Prerequisites:
- Server: A Linux server (VPS, cloud instance, bare metal) where you have root or sudo access.
- Docker: Install Docker Engine (instructions).
- Docker Compose: Install Docker Compose (instructions). Often comes with Docker Desktop, but needs separate install on servers.
- Git:
sudo apt update && sudo apt install git
or equivalent.
Step 1: Clone the Repository
git clone --depth 1 https://github.com/supabase/docker.gitcd docker
Step 2: Configure the Environment (.env)
This is the most critical step. Copy the example file and then edit it carefully:
cp .env.example .envnano .env # or use your preferred editor
Let's break down key sections in .env:
General
- POSTGRES_PASSWORD: CRITICAL! Set a strong, unique password for the database superuser. Use a password manager or generate one (e.g.,
openssl rand -hex 32
). - JWT_SECRET: CRITICAL! A secret used to sign JWTs. Must be at least 32 characters long. Generate a strong, unique random string (e.g.,
openssl rand -hex 32
). Do not use the default. - ANON_KEY: CRITICAL! This key grants anonymous access. It's derived from the JWT_SECRET by default, but you MUST replace the default placeholder with a generated, valid JWT signed with your JWT_SECRET.
- SERVICE_ROLE_KEY: CRITICAL! This key grants full admin access, bypassing RLS. It's derived from the JWT_SECRET by default, but you MUST replace the default placeholder.
- SITE_URL: The base URL of your frontend application (e.g., https://myapp.com).
- API_EXTERNAL_URL: The public URL where your Supabase API will be accessible.
Mailer (Setting up Email)
- To send emails (confirmations, resets), configure an SMTP provider.
- ENABLE_EMAIL_AUTOCONFIRM=false: Set to true if you want users to be active immediately after signup (less secure).
- SMTP_HOST: Your SMTP provider's hostname (e.g., smtp.sendgrid.net).
- SMTP_PORT: The port (e.g., 587 or 465).
- SMTP_USER: Your SMTP username.
- SMTP_PASS: Your SMTP password or API key.
- SMTP_SENDER_NAME: The "From" name in emails.
- SMTP_ADMIN_EMAIL: The email address emails are sent from.
Kong
- KONG_HTTP_PORT / KONG_HTTPS_PORT: Ports Kong (the API gateway) listens on. Default is 8000 / 8443.
Storage
- FILE_SIZE_LIMIT: Max upload size (e.g., 50MB).
Generating Secure Keys (Example using openssl):
# For JWT_SECRET (at least 32 chars)openssl rand -hex 32# For POSTGRES_PASSWORD (strong password)openssl rand -base64 32
For ANON_KEY and SERVICE_ROLE_KEY, you need valid JWTs. Use a tool or library to generate these based on your chosen JWT_SECRET. DO NOT USE THE EXAMPLE KEYS.
Step 3: (Optional) Customize docker-compose.yml
You might want to customize docker-compose.yml for:
Resource Limits:
services:db:# ... other configdeploy:resources:limits:cpus: '1.0'memory: 4G# Or older syntax:# mem_limit: 4g# cpus: 1.0
Volume Mounts:
volumes:db_data: # Docker managed volume (default)# OR map to a host path (example):services:db:volumes:- /path/on/your/host/postgres_data:/var/lib/postgresql/data
Caution: Back up the original docker-compose.yml before making significant changes. Incorrect modifications can break the stack.
Step 4: Launch the Supabase Stack
Once .env is configured (and docker-compose.yml optionally customized), start the services:
docker compose up -d
This will pull the necessary images and start all the containers in detached mode (-d).
Check the status:
docker compose ps
You should see all services running (db, kong, auth, realtime, storage, etc.). View logs if needed: docker compose logs -f <service_name>
Step 5: Access Your Self-Hosted Instance
- API URL: Access the API via the API_EXTERNAL_URL you set in .env.
- Studio: By default, Studio isn't included in the core docker-compose.yml. You'll need to run it separately if desired.
- Database: Connect directly using the POSTGRES_PASSWORD and the database port (default 5432).
- Connect Your App: Use the API_EXTERNAL_URL and the generated ANON_KEY / SERVICE_ROLE_KEY in your application's Supabase client configuration.
Step 6: Applying Migrations
Migrations created during local CLI development (in the supabase/migrations folder) are just SQL files. You can apply them to your self-hosted database using:
psql:
psql -h your-server-ip -p 5432 -U postgres -d postgres -f supabase/migrations/your_migration.sql
Database GUI:
Use a tool like DBeaver, pgAdmin, or even the locally running Supabase Studio (if configured to point to the self-hosted DB) to execute the migration SQL.
Conclusion: Choose Your Path
- Supabase CLI (supabase start) is perfect for local development – fast, easy, and ephemeral.
- Self-Hosting (supabase/docker) offers ultimate control and persistence for staging/production but demands significant operational responsibility for security, backups, and maintenance.
Understanding both methods allows you to leverage Supabase effectively throughout your development lifecycle, from initial coding sprints on your laptop to deploying a robust, customized backend on your own infrastructure. Happy building!