Skip to Content

Self-Host Supabase Docker: Your Complete Backend in 15 Minutes

Deploy a production-ready Postgres backend with auth, storage, and real-time APIs on your own infrastructure using Docker.

Self-Host Supabase Docker: Your Complete Backend in 15 Minutes

Firebase was great until you needed to own your data. Supabase gives you the same developer experience—Postgres, auth, storage, real-time—with full control. This self-host Supabase Docker guide gets you running on your own server in under 15 minutes.

What Is Supabase?

Supabase is an open-source Firebase alternative built on PostgreSQL. Self-hosting it gives you a complete backend platform without vendor lock-in or per-seat pricing.

What you get out of the box:

  • PostgreSQL—the world's most trusted relational database
  • Auto-generated REST and GraphQL APIs—no backend code required
  • Authentication—OAuth, email/password, magic links, SSO
  • Row Level Security—fine-grained access control at the database level
  • Storage—S3-compatible object storage for files and images
  • Realtime—WebSocket subscriptions for live data
  • Edge Functions—serverless TypeScript functions

For more context on why this matters, see our take on Supabase's momentum in the developer ecosystem. If you want deeper dives, check our guides on owning your backend with Supabase and self-hosting from scratch.

Prerequisites

Before starting this self-host Supabase Docker setup, confirm you have:

Required

  • A Linux server (Ubuntu 22.04+ recommended) with SSH access
  • Docker Engine 24.0+ and Docker Compose v2+
  • Git installed
  • At least 4GB RAM (8GB+ recommended)
  • 40GB SSD storage minimum (80GB+ for production)

Recommended

  • 4 CPU cores for smooth multi-service operation
  • A domain name pointing to your server (for HTTPS)
  • Swap space (4GB+) to prevent OOM kills

Quick Server Prep

# Update system
sudo apt update && sudo apt upgrade -y

# Install Docker
sudo apt install -y docker.io docker-compose-v2 git

# Add user to docker group
sudo usermod -aG docker $USER
newgrp docker

# Verify
docker --version
docker compose version
git --version

Step 1: Get the Supabase Docker Configuration

Supabase distributes its Docker setup through the official repository. You have two options: the automated quick-start script (Linux only) or manual clone.

Option A: Quick Start Script (Linux)

# Run the automated installer
curl -fsSL https://supabase.link/setup.sh | sh

# The script will:
# - Install prerequisites (git, openssl, jq)
# - Clone the docker/ directory from the Supabase repo
# - Generate all secrets and JWT keys
# - Prompt for your URLs
# - Pull Docker images

# After it finishes, start the stack:
cd supabase-project && sh run.sh start

Option B: Manual Clone (Any OS)

# Clone the repository
git clone --depth 1 https://github.com/supabase/supabase

# Create your project directory
mkdir supabase-project
cp -rf supabase/docker/* supabase-project/
cp supabase/docker/.env.example supabase-project/.env

# Enter project directory
cd supabase-project

# Pull images
docker compose pull

Step 2: Generate Secrets and Configure URLs

Never run Supabase with default passwords. Generate secure secrets before starting.

# Generate keys and secrets
sh utils/generate-keys.sh

# Add new auth keys and asymmetric JWT signing pair
sh utils/add-new-auth-keys.sh

Now edit the .env file to set your URLs:

# Edit .env
nano .env

# Set these to your actual domain or IP:
SUPABASE_PUBLIC_URL=http://your-domain.com:8000
API_EXTERNAL_URL=http://your-domain.com:8000/auth/v1
SITE_URL=http://your-domain.com:3000

# Set a secure dashboard password (must include at least one letter)
DASHBOARD_PASSWORD=YourSecurePassword123
DASHBOARD_USERNAME=admin

Review the generated secrets in .env before proceeding. The key values you'll need for your app:

  • POSTGRES_PASSWORD—database password
  • SUPABASE_PUBLISHABLE_KEY—client-side API key
  • SUPABASE_SECRET_KEY—server-side API key (keep secret)

Step 3: Start the Stack

Launch all services:

# Start all services and wait for health checks
sh run.sh start

# Check status
docker compose ps

# All services should show "Up (healthy)" within a minute

If any service shows created but not Up, check logs:

# Test script for common issues
sh tests/test-container-logs.sh

# Check logs for a specific service
sh run.sh logs auth
sh run.sh logs storage
sh run.sh logs realtime

Step 4: Access the Dashboard and APIs

Once all services are healthy, access Supabase Studio:

# View your credentials anytime
sh run.sh secrets

# Studio URL: http://your-domain.com:8000
# Login with DASHBOARD_USERNAME and DASHBOARD_PASSWORD

API Endpoints

All APIs route through the Kong gateway on port 8000:

  • REST API: http://your-domain.com:8000/rest/v1/
  • Auth API: http://your-domain.com:8000/auth/v1/
  • Storage API: http://your-domain.com:8000/storage/v1/
  • Realtime API: http://your-domain.com:8000/realtime/v1/

Connect to Postgres

Use the Supavisor connection pooler:

# Session mode (direct Postgres connection)
psql 'postgres://postgres.your-tenant-id:POSTGRES_PASSWORD@your-domain:5432/postgres'

# Transaction mode (pooled)
psql 'postgres://postgres.your-tenant-id:POSTGRES_PASSWORD@your-domain:6543/postgres'

Step 5: Test Edge Functions

The default setup includes a sample function. Test it:

# Test the default hello function
curl http://your-domain.com:8000/functions/v1/hello

# Add new functions in volumes/functions//index.ts
# Then recreate the functions service:
sh run.sh recreate functions

Step 6: Secure for Production

Running on HTTP over port 8000 is fine for development. Production needs HTTPS.

Reverse Proxy with HTTPS

Place Nginx or Caddy in front of the Kong gateway. Here's a basic Nginx config:

server {
    listen 80;
    server_name api.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name api.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 86400;
    }
}

After setting up HTTPS, update your .env URLs to use https:// and port 443:

SUPABASE_PUBLIC_URL=https://api.yourdomain.com
API_EXTERNAL_URL=https://api.yourdomain.com/auth/v1
SITE_URL=https://app.yourdomain.com

Then recreate the services:

sh run.sh recreate

Firewall Rules

sudo ufw allow 22/tcp     # SSH
sudo ufw allow 80/tcp     # HTTP (Certbot)
sudo ufw allow 443/tcp    # HTTPS
sudo ufw deny 8000/tcp    # Block direct Kong access
sudo ufw enable

Tips and Troubleshooting

"Service unhealthy" after startup

Check which service is failing:

docker compose ps
sh run.sh logs 

# Common fixes:
# - Increase RAM/swap
# - Check that ports aren't already in use
# - Verify .env values are set correctly

Kong fails with entrypoint error

Your files may have CRLF line endings. Fix:

# Re-clone with proper line endings
git clone --depth 1 https://github.com/supabase/supabase
# Or convert existing files:
sudo apt install -y dos2unix
find . -type f -name "*.sh" -exec dos2unix {} \;

Out of memory errors

Supabase runs 10+ services. If you're resource-constrained, remove services you don't need from docker-compose.yml:

  • Remove realtime if you don't need live subscriptions
  • Remove imgproxy if you don't need image transformations
  • Remove functions if you don't use Edge Functions

Enable analytics (optional)

Logs & Analytics are disabled by default to save resources. Enable them:

sh run.sh config add logs
sh run.sh start

This adds Logflare and Vector services. Expect higher RAM usage.

Updating Supabase

# Pull latest images
sh run.sh pull

# Recreate services with new images
sh run.sh recreate

# Or update a single service:
# Edit docker-compose.yml image tag, then:
sh run.sh pull
sh run.sh recreate studio

Backup your database

# Dump the database
docker compose exec db pg_dump -U postgres postgres > backup-$(date +%Y%m%d).sql

# Backup storage volumes
docker run --rm -v supabase-project_storage:/data -v $(pwd):/backup alpine \
  tar czf /backup/supabase-storage-$(date +%Y%m%d).tar.gz -C /data .

Reset everything (destructive)

# WARNING: This deletes all data
sh reset.sh

# Skip confirmation:
sh reset.sh -y

What's Next?

You now have a fully self-hosted backend platform. Here's where to go from here:

  • Connect your frontend—use the Supabase client library with your SUPABASE_PUBLIC_URL and SUPABASE_PUBLISHABLE_KEY
  • Set up auth providers—configure Google, GitHub, or email auth in Studio
  • Enable Row Level Security—define policies to protect your data
  • Create storage buckets—upload and serve files with automatic transformations
  • Write Edge Functions—deploy serverless TypeScript for custom logic
  • Set up backups—automate database dumps and volume snapshots

Supabase releases self-hosted updates monthly. Follow the self-hosted changelog and GitHub Discussions to stay current.

Need Help With Production Deployment?

This self-host Supabase Docker guide gets you running, but production deployments need more: HA Postgres, automated backups, monitoring, SSO configuration, and compliance hardening.

If you're building on Supabase and need infrastructure expertise, get in touch with our team. We specialize in self-hosted backend platforms that scale with your product.

Portainer Docker Setup: Stop Managing Containers from the Terminal
Deploy Portainer on any Docker host and get a visual dashboard to manage containers, stacks, networks, and volumes without memorizing CLI flags.