NITAI IT SOLUTION

Complete Guide to Self-Hosting Supabase on Ubuntu VPS with Docker & Nginx Reverse Proxy

Step-by-step production deployment of open-source Supabase: configuring Postgres, GoTrue auth, PostgREST, Kong gateway, SSL certificates, and automated nightly backups.

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:

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.

Schedule Free Technical Consultation Chat with Lead Architect