This guide walks you through deploying a complete Supabase stack using Docker Compose. This is the recommended method for self-hosting Supabase.
Prerequisites
Before starting, ensure you have:
Install Git
# Ubuntu/Debian
sudo apt-get install git
# macOS
brew install git
# Verify installation
git --version
Install Docker
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Verify installation
docker --version
docker compose version
Docker Compose v2 is required (included with Docker Engine 20.10+). The command is docker compose, not docker-compose.
Quick Start
Clone Repository
# Clone Supabase repository
git clone --depth 1 https://github.com/supabase/supabase
# Navigate to Docker directory
cd supabase/docker
Copy Environment File
# Copy example environment file
cp .env.example .env
The default .env.example file contains insecure default passwords. Never use these in production!
Generate Secrets
Generate secure passwords and JWT secrets: # Use the provided script
sh ./utils/generate-keys.sh
Or generate manually: # Generate random passwords (32 characters)
openssl rand -base64 32
# Generate JWT secret (minimum 32 characters)
openssl rand -base64 32
Update your .env file with generated values:
Start Supabase
# Pull latest images
docker compose pull
# Start all services
docker compose up -d
# View logs
docker compose logs -f
Wait for all services to become healthy (1-2 minutes).
Access Dashboard
Open your browser to: Default credentials:
Username: supabase (or your DASHBOARD_USERNAME)
Password: From your .env file
You now have a fully functional Supabase instance running locally!
Docker Compose Configuration
The docker-compose.yml file defines all Supabase services:
Included Services
services :
# Supabase Studio - Dashboard at :3000
studio :
image : supabase/studio:2026.02.16-sha-26c615c
# Kong API Gateway - Public endpoint at :8000
kong :
image : kong:2.8.1
ports :
- "8000:8000" # HTTP
- "8443:8443" # HTTPS
# GoTrue Authentication - :9999
auth :
image : supabase/gotrue:v2.186.0
# PostgREST API - :3000
rest :
image : postgrest/postgrest:v14.5
# Realtime Server - :4000
realtime :
image : supabase/realtime:v2.76.5
# Storage API - :5000
storage :
image : supabase/storage-api:v1.37.8
# Image Proxy - :5001
imgproxy :
image : darthsim/imgproxy:v3.30.1
# Postgres Metadata - :8080
meta :
image : supabase/postgres-meta:v0.95.2
# Edge Functions Runtime - :8081
functions :
image : supabase/edge-runtime:v1.70.3
# Analytics/Logging - :4000
analytics :
image : supabase/logflare:1.31.2
# PostgreSQL Database - :5432
db :
image : supabase/postgres:15.8.1.085
# Vector Log Pipeline - :9001
vector :
image : timberio/vector:0.53.0-alpine
# Connection Pooler - :6543
supavisor :
image : supabase/supavisor:2.7.4
ports :
- "5432:5432" # Session mode
- "6543:6543" # Transaction mode
Service Versions
Latest stable versions as of February 2026:
Studio : 2026.02.16
Auth (GoTrue) : v2.186.0
PostgREST : v14.5
Realtime : v2.76.5
Storage : v1.37.8
Edge Runtime : v1.70.3
PostgreSQL : 15.8.1
See versions.md for complete version history.
Environment Configuration
Key environment variables in .env:
Secrets (MUST CHANGE)
# PostgreSQL password for 'postgres' user
POSTGRES_PASSWORD = your-super-secret-and-long-postgres-password
# JWT secret for signing tokens (min 32 characters)
JWT_SECRET = your-super-secret-jwt-token-with-at-least-32-characters-long
# Anonymous (public) JWT key
ANON_KEY = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Service role (admin) JWT key
SERVICE_ROLE_KEY = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Dashboard login credentials
DASHBOARD_USERNAME = supabase
DASHBOARD_PASSWORD = this_password_is_insecure_and_should_be_updated
URLs
# Public URL for API access
SUPABASE_PUBLIC_URL = http://localhost:8000
# External URL for OAuth callbacks
API_EXTERNAL_URL = http://localhost:8000
# Site URL for authentication redirects
SITE_URL = http://localhost:3000
Database
POSTGRES_HOST = db
POSTGRES_DB = postgres
POSTGRES_PORT = 5432
Storage
# Use 'file' for local storage or configure S3
STORAGE_BACKEND = file
# Directory name for local file storage
GLOBAL_S3_BUCKET = supabase-storage
For S3-compatible storage, see S3 Configuration .
Managing Services
Start/Stop Services
# Start all services
docker compose up -d
# Stop all services (keeps data)
docker compose stop
# Start specific service
docker compose up -d studio
# Restart all services
docker compose restart
View Logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f db
docker compose logs -f auth
# Last 100 lines
docker compose logs --tail=100 db
Check Service Health
# View service status
docker compose ps
# Check specific service health
docker compose ps db
Update Services
# Pull latest images
docker compose pull
# Recreate containers with new images
docker compose up -d
# Remove old images
docker image prune
Data Persistence
Docker volumes store persistent data:
# List volumes
docker volume ls | grep supabase
# Inspect database volume
docker volume inspect supabase_db-config
# Backup database volume
docker run --rm -v supabase_db-data:/data -v $( pwd ) :/backup \
ubuntu tar czf /backup/db-backup.tar.gz /data
Volume Locations
./volumes/
├── db/
│ ├── data/ # PostgreSQL data directory
│ ├── realtime.sql # Realtime migrations
│ ├── roles.sql # Database roles
│ └── jwt.sql # JWT configuration
├── storage/ # Uploaded files
├── functions/ # Edge Functions code
├── snippets/ # SQL snippets
├── api/
│ └── kong.yml # Kong configuration
└── logs/
└── vector.yml # Log pipeline config
Accessing Services
Database Access
Via Supavisor (Recommended) :
# Connection pooling - Transaction mode
psql "postgresql://postgres:your-password@localhost:6543/postgres"
Direct Connection :
psql "postgresql://postgres:your-password@localhost:5432/postgres"
Use connection pooling (port 6543) for web applications to avoid connection exhaustion.
API Endpoints
All APIs are accessible through Kong gateway:
# REST API
curl http://localhost:8000/rest/v1/your_table \
-H "apikey: YOUR_ANON_KEY"
# Auth API
curl http://localhost:8000/auth/v1/signup \
-H "apikey: YOUR_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password"}'
# Storage API
curl http://localhost:8000/storage/v1/object/list/bucket-name \
-H "apikey: YOUR_ANON_KEY"
Studio Dashboard
Access the web dashboard at http://localhost:8000 .
Advanced Configuration
S3 Storage
Use S3-compatible storage instead of local files:
# Start with S3 configuration
docker compose -f docker-compose.yml -f docker-compose.s3.yml up -d
Update .env with S3 credentials:
STORAGE_BACKEND = s3
GLOBAL_S3_BUCKET = your-bucket-name
GLOBAL_S3_ENDPOINT = https://s3.amazonaws.com
GLOBAL_S3_REGION = us-east-1
AWS_ACCESS_KEY_ID = your-access-key
AWS_SECRET_ACCESS_KEY = your-secret-key
Custom Domain
Configure Kong for custom domain:
# Update .env
SUPABASE_PUBLIC_URL = https://api.yourdomain.com
API_EXTERNAL_URL = https://api.yourdomain.com
Use nginx or Caddy as reverse proxy:
server {
listen 80 ;
server_name api.yourdomain.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
}
}
HTTPS/SSL
Enable SSL in Kong:
Generate or obtain SSL certificates
Uncomment SSL configuration in docker-compose.yml
Mount certificates in Kong container
Restart services
kong :
volumes :
- ./volumes/api/server.crt:/home/kong/server.crt:ro
- ./volumes/api/server.key:/home/kong/server.key:ro
environment :
KONG_SSL_CERT : /home/kong/server.crt
KONG_SSL_CERT_KEY : /home/kong/server.key
Troubleshooting
Check logs for errors: Common issues:
Port conflicts (8000, 5432 already in use)
Insufficient memory (less than 4GB available)
Docker daemon not running
Database Connection Fails
Verify Postgres is healthy: docker compose ps db
docker compose logs db
Check credentials in .env match connection string.
Studio Shows 'Invalid JWT'
Regenerate JWT keys: sh ./utils/generate-keys.sh
Update ANON_KEY and SERVICE_ROLE_KEY in .env, then restart:
Check storage volume permissions: ls -la volumes/storage
chmod -R 777 volumes/storage
docker compose restart storage
Reduce Postgres shared_buffers: # volumes/db/postgresql.conf
shared_buffers = 256MB # Default is 512MB
Restart database: docker compose restart db
Next Steps
Configuration Learn about environment variables and advanced config
Security Secure your installation for production
Updates Keep your stack up-to-date
Backup Set up automated backups