Self-Host Supabase Docker: Your Complete Guide to Owning Your Backend
You want the power of Supabase without the platform bills. You want your data on your servers. And you want it running in Docker, not some black-box managed service. This guide walks you through self-hosting the full Supabase stack—Postgres, Auth, Storage, Realtime, and Edge Functions—using Docker Compose. By the end, you'll have a production-ready backend you actually control.
For a deeper look at why self-hosting matters and the full architecture breakdown, check out our companion piece: Self-Host Supabase Docker: Run Your Own Firebase Alternative With Full Control.
What You'll Build
By the end of this guide, you'll have:
- The complete Supabase stack running via Docker Compose
- PostgreSQL with the Supavisor connection pooler
- Auth, Storage, Realtime, and Edge Functions services
- Supabase Studio dashboard accessible via your domain
- Proper secrets, JWT keys, and HTTPS configuration
- A working client connection from your frontend application
Prerequisites
Before you start, make sure you have:
- Docker 24.0+ and Docker Compose v2 installed
- Git installed for cloning the configuration
- At least 4GB RAM (8GB+ recommended for production)
- At least 2 CPU cores (4+ recommended)
- 40GB SSD minimum (80GB+ recommended)
- A server or VM with a static IP and ports
80,443, and8000accessible - A domain name pointing to your server (for production)
- Basic familiarity with Linux, networking, and environment variables
If you're looking for a from-scratch deep dive into every component, our detailed walkthrough covers it: Own Your Backend: How to Self-Host Supabase with Docker from Scratch.
Step 1: Get the Supabase Docker Configuration
Supabase distributes its Docker configuration as part of the official repository. You have two options: automated quick start (Linux only) or manual installation (any OS).
Option A: Quick Start (Linux)
If you're on Debian/Ubuntu or RHEL/CentOS/Fedora, the automated script handles everything:
curl -fsSL https://supabase.link/setup.sh | sh
This script installs prerequisites, clones the Docker configuration, generates all secrets and JWT keys, prompts for your URLs, and pulls the images. After it finishes:
cd supabase-project && \
sh run.sh start
Option B: Manual Installation (Any OS)
For non-Linux systems or if you prefer full control, clone the repository manually:
# Clone the Supabase repository
git clone --depth 1 https://github.com/supabase/supabase
# Create your project directory
mkdir supabase-project
# Copy Docker files
cp -rf supabase/docker/* supabase-project/
cp supabase/docker/.env.example supabase-project/.env
# Switch to project directory
cd supabase-project
# Pull latest images
docker compose pull
Step 2: Generate Secrets and Configure URLs
Never run Supabase with the example passwords. Generate secure secrets and configure your environment properly.
Generate Keys and Secrets
# Generate random passwords and secrets
sh utils/generate-keys.sh
# Add new API keys and asymmetric JWT key pair
sh utils/add-new-auth-keys.sh
Review the generated output and check your .env file before proceeding.
Configure Supabase URLs
Edit the .env file and set these critical variables:
# Base URL for accessing Supabase from the internet
SUPABASE_PUBLIC_URL=https://api.yourdomain.com
# Used by Auth service for callback URLs
API_EXTERNAL_URL=https://api.yourdomain.com
# Default redirect URL for Auth
SITE_URL=https://app.yourdomain.com
# Dashboard credentials (must contain at least one letter)
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=your-secure-password-here
Security note: The dashboard password must include at least one letter—don't use numbers only or special characters.
Step 3: Start the Supabase Stack
With secrets generated and URLs configured, start the stack:
sh run.sh start
This is equivalent to docker compose up -d --wait. It starts all services and waits until they're healthy. Check the status:
docker compose ps
All services should show Up [...] (healthy). If any container shows created but not Up, inspect the logs:
sh run.sh logs auth
sh run.sh logs storage
sh run.sh logs realtime
Step 4: Access Your Services
Once everything is healthy, access your services through the Kong API gateway.
Supabase Studio Dashboard
Open https://api.yourdomain.com (or http://your-server-ip:8000 without HTTPS). You'll be prompted for basic auth using the DASHBOARD_USERNAME and DASHBOARD_PASSWORD from your .env file.
API Endpoints
All APIs are available through the same gateway:
- REST:
https://api.yourdomain.com/rest/v1/ - Auth:
https://api.yourdomain.com/auth/v1/ - Storage:
https://api.yourdomain.com/storage/v1/ - Realtime:
https://api.yourdomain.com/realtime/v1/
Connect to PostgreSQL
Supabase includes the Supavisor connection pooler. Connect via session mode (direct equivalent):
psql 'postgres://postgres.your-tenant-id:[email protected]:5432/postgres'
Or transaction mode (connection pooling):
psql 'postgres://postgres.your-tenant-id:[email protected]:6543/postgres'
Step 5: Configure HTTPS with a Reverse Proxy
For production, you need HTTPS. The recommended approach is placing a reverse proxy in front of Kong.
Caddy Example
# Caddyfile
api.yourdomain.com {
reverse_proxy localhost:8000
}
Nginx Example
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:8000;
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;
}
}
After setting up the reverse proxy, update your .env URLs to use https://api.yourdomain.com and restart the stack.
Step 6: Connect Your Application
Now connect your frontend to your self-hosted Supabase instance.
JavaScript/TypeScript Client
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://api.yourdomain.com'
const supabaseKey = 'your-publishable-anon-key'
const supabase = createClient(supabaseUrl, supabaseKey)
// Example: fetch data
const { data, error } = await supabase
.from('posts')
.select('*')
Find your credentials by running:
sh run.sh secrets
The key values you need:
SUPABASE_PUBLISHABLE_KEY— for client-side code (safe to expose)SUPABASE_SECRET_KEY— for server-side only (never expose this)POSTGRES_PASSWORD— for direct database connectionsSUPABASE_PUBLIC_URL— the URL passed tocreateClient
Security Hardening Checklist
Before calling this production-ready:
Change All Default Secrets
Run sh utils/generate-keys.sh and sh utils/add-new-auth-keys.sh to replace every placeholder in .env. Never commit the .env file.
Enable HTTPS
Always use HTTPS in production. Set up a reverse proxy with valid TLS certificates (Let's Encrypt is free).
Secure the Dashboard
Use a strong, unique password for DASHBOARD_PASSWORD. Consider restricting dashboard access by IP or VPN.
Database Access
Don't expose Postgres directly to the internet. Use Supavisor or connect via your application's internal network. If you must expose it, restrict to specific IPs:
# In docker-compose.yml, under the db service
ports:
- "127.0.0.1:5432:5432" # Local only
# OR specific IP
- "10.0.0.5:5432:5432"
Backups
Set up automated PostgreSQL backups:
#!/bin/bash
# backup-supabase.sh
CONTAINER=supabase-db
BACKUP_DIR=/backups
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
docker exec $CONTAINER pg_dump -U supabase postgres \
| gzip > "$BACKUP_DIR/supabase-$TIMESTAMP.sql.gz"
# Keep only last 7 days
find $BACKUP_DIR -name 'supabase-*.sql.gz' -mtime +7 -delete
Add to crontab for daily backups:
0 2 * * * /path/to/backup-supabase.sh
Tips and Troubleshooting
Service won't start or shows unhealthy
Check container logs first:
sh run.sh logs
# or
docker compose logs --tail=100
Common culprits: insufficient memory, port conflicts, or missing environment variables.
Port 8000 already in use
sudo lsof -i :8000
# or
ss -tlnp | grep 8000
Change the host port in docker-compose.yml or stop the conflicting service.
Out of memory errors
Supabase is resource-intensive. If you see OOM kills:
- Upgrade to 8GB+ RAM
- Remove unused services from
docker-compose.yml(Realtime, Storage, imgproxy, Edge Functions) - Add swap space as a temporary buffer
Auth redirects failing
Ensure SITE_URL and API_EXTERNAL_URL in .env exactly match your actual domain. Auth callbacks are strict about URL matching.
Edge Functions not updating
A plain restart doesn't pick up function changes. Force recreate:
sh run.sh recreate functions
Updating Supabase
Supabase releases stable Docker versions monthly. To update:
# Pull latest images
sh run.sh pull
# Recreate containers with new images
sh run.sh recreate
Always check the self-hosted changelog before updating.
Reset everything (destructive)
If you need to start completely fresh:
sh reset.sh
Warning: This destroys all data, including the database and storage volumes. It backs up .env to .env.old first.
Next Steps
You now have a self-hosted Supabase instance running on Docker. From here, you can:
- Set up Row Level Security (RLS) policies in your database
- Configure OAuth providers (Google, GitHub, etc.) in Auth settings
- Enable Storage buckets with proper access controls
- Deploy custom Edge Functions for serverless logic
- Set up Realtime subscriptions for live data
- Enable Logs & Analytics for monitoring
For a comprehensive walkthrough of the full architecture and advanced configuration, read our deep-dive guide: Own Your Backend: How to Self-Host Supabase with Docker from Scratch.
And if you want to understand why Supabase is becoming the go-to backend for modern development, check out our coverage of their momentum: Supabase Doubles Its Valuation to $10B in Just 8 Months, Riding the Vibe-Coding Wave.
Already comfortable with the basics and want the full control overview? See: Self-Host Supabase Docker: Run Your Own Firebase Alternative With Full Control.
Need Help With Production Supabase?
Self-hosting Supabase gives you full control, but it also means you're responsible for security, backups, scaling, and uptime. If your team needs help architecting a production-grade Supabase deployment, configuring SSO, setting up monitoring, or migrating from managed Supabase to self-hosted, get in touch with our team at Sysbrix. We've built and maintained self-hosted backends for startups and enterprises—and we can get yours running right.