Supabase has emerged as the premier open-source Firebase alternative, providing developers with a relational PostgreSQL database, real-time WebSockets, auto-generated REST/GraphQL APIs (via PostgREST), built-in user authentication (GoTrue), and S3-compatible file storage. While Supabase Cloud offers a generous managed tier, enterprise regulatory compliance (GDPR, HIPAA, data residency) or high-volume usage often makes self-hosting on dedicated cloud VPS (AWS, DigitalOcean, Hetzner) 80% more cost-effective. This guide walks through a production self-hosted deployment.
Hardware Prerequisites for Self-Hosting Supabase
Because Supabase bundles multiple containerized microservices (PostgreSQL, PostgREST, GoTrue, Realtime, Storage, Kong API Gateway, and Studio Dashboard), ensure your VPS meets minimum hardware specifications:
- Development / Staging: 2 vCPUs, 4GB RAM, 40GB NVMe SSD ($10–$15/month).
- Production Workload: 4+ dedicated vCPUs, 8GB–16GB RAM, 100GB+ NVMe SSD ($30–$60/month).
- Operating System: Ubuntu 24.04 LTS with Docker & Docker Compose v2.
Step 1: Clone Official Supabase Docker Repository
# SSH into your clean Ubuntu VPS
ssh ubuntu@your-server-ip
# Install Docker & Git
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl docker.io docker-compose-v2
sudo systemctl enable --now docker
# Clone Supabase official deployment template
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
# Create local environment config
cp .env.example .env
Step 2: Hardening the .env Secrets Configuration
Before launching containers, you must replace default example passwords. Leaving default JWT secrets will allow anyone on the internet to mint admin tokens:
# Generate strong 64-character random secrets via openssl
openssl rand -hex 32
# In .env, update these mandatory security variables:
POSTGRES_PASSWORD=your_super_strong_db_password_here
JWT_SECRET=your_super_secure_jwt_secret_at_least_32_chars
ANON_KEY=generated_jwt_token_with_role_anon
SERVICE_ROLE_KEY=generated_jwt_token_with_role_service_role
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=your_secure_admin_password
Security Hardening: UFW Firewall & Docker Port Exposure
By default, Docker bypasses standard Linux UFW (Uncomplicated Firewall) iptables rules. This means if your docker-compose.yml binds ports like 5432:5432 (PostgreSQL) or 8000:8000 (Kong API) to 0.0.0.0, your database is exposed directly to the public internet, open to brute-force bot attacks.
To prevent this, bind internal services strictly to the loopback interface (127.0.0.1:5432:5432) or communicate entirely within an internal Docker bridge network. Only ports 80 (HTTP) and 443 (HTTPS) managed by Nginx should be reachable from the external WAN.
Step 3: Launch Containers & Nginx SSL Reverse Proxy
# Start all Supabase containers in detached background mode
sudo docker compose up -d
# Verify all containers are healthy
sudo docker compose ps
Configure Nginx as a reverse proxy fronting Kong (port 8000) and Studio Dashboard (port 3000), issuing a free SSL certificate via Let's Encrypt Certbot:
# /etc/nginx/sites-available/supabase.conf
server {
server_name supabase.yourdomain.com;
location / {
proxy_pass http://localhost:8000; # Kong API Gateway
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;
}
}
# Issue SSL Certificate
sudo certbot --nginx -d supabase.yourdomain.com
Automated Database Backup Strategy
Never run production databases without verified offsite backups. Create a daily automated backup script:
#!/bin/bash
# /opt/scripts/backup_supabase.sh
BACKUP_DIR="/opt/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
FILENAME="$BACKUP_DIR/supabase_db_$TIMESTAMP.sql.gz"
mkdir -p $BACKUP_DIR
sudo docker exec -t supabase-db pg_dumpall -U postgres | gzip > $FILENAME
# Upload to Amazon S3 or Cloudflare R2
aws s3 cp $FILENAME s3://my-encrypted-backups/supabase/
# Purge local backups older than 7 days
find $BACKUP_DIR -type f -mtime +7 -delete
Frequently Asked Questions
Can I upgrade self-hosted Supabase without downtime?
Yes. By running git pull in the supabase/docker folder and executing docker compose pull && docker compose up -d, Docker gracefully recreates updated container layers while preserving persistent PostgreSQL data volumes.
Is self-hosted Supabase missing any features from Supabase Cloud?
The core database, auth, storage, realtime, and studio dashboard are 100% identical. The only features exclusive to Supabase Cloud are managed multi-region branching, one-click point-in-time recovery (PITR) GUI, and serverless edge functions autoscaling across Vercel/Fly.io networks.
Need Help Implementing This in Production?
Our senior engineering team helps startups and enterprises scale web applications, migrate cloud infrastructure, and build custom AI workflows with guaranteed delivery timelines.