To self-host Supabase on a VPS, you need an Ubuntu server with at least 4 GB of RAM (8 GB or more is recommended), Docker and Docker Compose, the official Supabase docker folder, a strong .env file, and a reverse proxy such as Caddy for HTTPS. You copy the files, replace every default secret, run docker compose up -d, and Supabase Studio is live in about 15 minutes.
This guide walks through every step on a fresh Ubuntu VPS: sizing the server, installing Docker, generating secrets, starting the stack, adding a domain with HTTPS, setting up email, locking down ports, scheduling backups and updating safely. Commands are copy-ready, and each step says what it does and why it matters.
What Does It Mean to Self-Host Supabase?
Supabase is an open source backend built on Postgres. It bundles a database, user authentication, instant REST APIs, realtime subscriptions, file storage and Edge Functions. Supabase also offers a hosted cloud service, but because the code is open source you can run the same stack on your own server.
Self-hosting means you run those services yourself, usually as Docker containers behind one API gateway. You choose where the data lives, you control the version, and your server cost stays predictable. The trade-off is that you handle updates, backups, HTTPS and email delivery, which this tutorial covers.
What You Need Before You Start
- A VPS running Ubuntu 22.04 or 24.04 with root or sudo access.
- A domain or subdomain such as
api.yourdomain.compointed at the server IP, needed for HTTPS in production. - An SMTP account from any email provider, so sign-up and password reset emails can be delivered.
- Basic terminal skills: connecting over SSH and editing a file with nano.
How Much Server Do You Need for Supabase?
Supabase publishes its own requirements for self-hosting. A single install runs more than ten containers, so it needs more headroom than a typical web app.
| Level | RAM | CPU | Disk |
|---|---|---|---|
| Minimum | 4 GB | 2 cores | 40 GB SSD |
| Recommended | 8 GB or more | 4 cores or more | 80 GB or more SSD |
Memory is the first limit you will hit, and turning on optional Logs and Analytics services raises the need further. For a trial, a 4 GB server will start the stack. For real users, start at 8 GB RAM with 2 vCPU, and choose 16 GB with 4 vCPU for a production app. A fast NVMe disk helps Postgres more than almost any other setting. Our Supabase VPS hosting page shows which plan fits which workload and the locations available in India, the USA and the Netherlands.
Need a Server That Fits Supabase?
Our Supabase VPS plans start with the 8 GB RAM that Supabase recommends, come with NVMe storage, a free dedicated IPv4 and full root access, and are available in India, the USA and the Netherlands.
Step 1: Connect to the VPS and Update Ubuntu
Log in over SSH, then update the system packages and create a working user if you do not want to run everything as root.
ssh root@YOUR_SERVER_IP
apt update && apt upgrade -yReboot if the upgrade installed a new kernel, then reconnect.
Step 2: Install Docker and Docker Compose
Supabase self-hosting is built around Docker Compose. Docker publishes an install script that sets up Docker Engine and the Compose plugin in one go.
curl -fsSL https://get.docker.com | sh
docker --version
docker compose versionBoth commands should print a version number. If you want a deeper look at running containers on a server, see how a Docker VPS is set up and sized.
Step 3: Download the Official Supabase Docker Files
Clone the Supabase repository, then copy only its docker folder and the example environment file into a project directory. Keeping your project separate from the clone makes later updates easier.
git clone --depth 1 https://github.com/supabase/supabase
mkdir supabase-project
cp -rf supabase/docker/* supabase-project
cp supabase/docker/.env.example supabase-project/.env
cd supabase-projectThe folder now contains docker-compose.yml, the .env file and a few helper folders for volumes and configuration.
Step 4: Replace Every Default Secret
This is the most important step. The example .env file ships with placeholder passwords and keys that are public. Anyone who knows them can open your database, so replace all of them before the first start.
Open the file with nano .env and change these values:
POSTGRES_PASSWORD: a long random password for the database.JWT_SECRET: a random string of at least 32 characters. Every token is signed with it.ANON_KEYandSERVICE_ROLE_KEY: API keys that must be generated from your JWT secret.DASHBOARD_USERNAMEandDASHBOARD_PASSWORD: the login for Supabase Studio.SECRET_KEY_BASE,VAULT_ENC_KEYandPG_META_CRYPTO_KEY: random strings used for internal encryption.POOLER_TENANT_ID: any short unique name for the connection pooler.
You can create random values with openssl rand -hex 32. Newer versions of the repository also include a key helper in the utils folder, so check for it first:
ls utils
sh ./utils/generate-keys.shIf the helper is not there, generate a 32-plus character JWT_SECRET yourself, then create the ANON_KEY and SERVICE_ROLE_KEY as JWT tokens signed with that secret, using the anon and service_role roles. Never reuse the example keys, and never share the service role key with a browser or mobile app, because it bypasses Row Level Security.
Step 5: Set Your URLs in the .env File
Tell Supabase the address it will be reached at. Replace the localhost defaults with your real domain once you have set it up in Step 7.
SUPABASE_PUBLIC_URL=https://api.yourdomain.com
API_EXTERNAL_URL=https://api.yourdomain.com
SITE_URL=https://yourapp.comSITE_URL is where users are sent after email confirmation, so point it at your front-end app. If you are only testing, leave the defaults and use the server IP.
Step 6: Start Supabase
Pull the images, then start every service in the background.
docker compose pull
docker compose up -d
docker compose psThe first pull takes a few minutes. When docker compose ps shows the containers as running or healthy, the stack is up. If one keeps restarting, read its log with docker compose logs db or the name of the service that failed. Most first-start problems are a weak or badly formatted value in the .env file.
Supabase Studio and the API now answer on port 8000 of your server. Open http://YOUR_SERVER_IP:8000, sign in with the dashboard username and password you set, and you will see the Studio dashboard. Test the API with your anon key:
curl http://localhost:8000/rest/v1/ -H "apikey: YOUR_ANON_KEY"Step 7: Add a Domain and HTTPS With Caddy
Plain HTTP on a raw IP is fine for a test, but production needs HTTPS. OAuth sign-in providers also require it. A reverse proxy sits in front of the Supabase gateway, handles the certificate and forwards traffic to port 8000. Caddy is the simplest option because it gets and renews certificates automatically.
First create a DNS A record that points api.yourdomain.com to your server IP. Then install Caddy and write its config:
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
apt install -y caddy
nano /etc/caddy/Caddyfileapi.yourdomain.com {
reverse_proxy localhost:8000
}systemctl reload caddyWithin a minute, https://api.yourdomain.com loads Studio with a valid certificate. If you installed Nginx instead, the idea is the same: proxy the domain to localhost:8000 and add a certificate with Certbot.
Step 8: Configure Email for Sign-Ups and Password Resets
Out of the box the example file uses a fake mail container. For real users you need a production SMTP server, otherwise confirmation and reset emails never arrive. Fill in the SMTP values from your email provider in the .env file:
[email protected]
SMTP_HOST=smtp.yourprovider.com
SMTP_PORT=587
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
SMTP_SENDER_NAME=Your AppApply the change by recreating the containers, then sign up a test user and confirm the email arrives.
docker compose up -dStep 9: Lock Down the Ports
A common mistake is leaving database and admin ports open to the whole internet. Allow only what you need through the firewall:
ufw allow OpenSSH
ufw allow 80
ufw allow 443
ufw enableThere is one catch. Docker publishes container ports by writing its own firewall rules, so a port listed in docker-compose.yml can stay reachable even when UFW blocks it. After Caddy is working, edit the compose file so the gateway only listens locally, for example by changing the Kong port mapping to 127.0.0.1:8000:8000, and review the Postgres and pooler port mappings the same way unless you truly need outside database access. Then run docker compose up -d again.
Also keep SSH safe: use key login, disable password login if you can, and never expose Studio without the dashboard password you set in Step 4.
Step 10: Schedule Database Backups
When you self-host, backups are your job. Create a small script that dumps Postgres from the database container and keeps the last 7 days.
mkdir -p /root/backups
nano /root/backup-supabase.sh#!/bin/bash
set -e
DIR=/root/backups
FILE=$DIR/supabase-$(date +%F).sql.gz
docker exec supabase-db pg_dumpall -U postgres | gzip > "$FILE"
find $DIR -name 'supabase-*.sql.gz' -mtime +7 -deletechmod +x /root/backup-supabase.sh
crontab -e
# add this line to run every night at 2 AM:
0 2 * * * /root/backup-supabase.shAlso back up the project folder, because it holds your .env file and the storage volume with uploaded files. A backup is only real once you have restored it somewhere, so test a restore on a spare server at least once. Copy the dumps off the VPS too, since a backup on the same disk does not survive a disk failure.
Step 11: Update Supabase Safely
Supabase releases new image versions often. Read the changelog of the new version first, because some updates need a configuration change. Then take a backup and update:
cd ~/supabase-project
docker compose pull
docker compose down
docker compose up -dUpdate during a quiet hour, and keep the previous docker-compose.yml and .env so you can roll back. Do not upgrade production blindly: try the new version on a staging VPS first.
Common Problems and Fixes
| Problem | Likely cause | Fix |
|---|---|---|
| A container keeps restarting | Bad or short value in the .env file | Check logs with docker compose logs SERVICE and correct the value |
| Out of memory, services killed | Server too small for the stack | Move to a plan with 8 GB RAM or more, or add swap while you resize |
| Studio opens but the API returns 401 | Wrong anon key or JWT secret mismatch | Regenerate both keys from the same JWT secret and recreate containers |
| No confirmation emails arrive | SMTP not configured | Set the SMTP values in .env and run docker compose up -d |
| HTTPS certificate fails | DNS not pointing to the server yet | Check the A record, wait for it to propagate, then reload Caddy |
| Login redirects to localhost | SITE_URL or API_EXTERNAL_URL still default | Set both to your real URLs and recreate the containers |
Which VPS Should You Use for Self-Hosted Supabase?
Pick a KVM VPS with full root access, because Docker needs it, and choose NVMe storage for Postgres. Dedicated CPU and RAM matter, since shared resources make database queries slow and unpredictable. Choose the location closest to your users to cut response time. Ubuntu is the safest operating system because most Supabase and Docker guides assume it.
A YouStable VPS gives you all of that, with plans in India, the USA and the Netherlands, INR billing and 24/7 chat, ticket and email support. Remember the split of responsibility: we run the hardware, network and uptime, and you manage the Supabase install, updates and backups. For the full range of servers, browse our VPS hosting plans.
FAQs
Is Supabase free to self-host?
Yes. Supabase is open source, so the software is free. You pay only for the server, your domain and any email service.
How long does a Supabase self-host install take?
The official guide says a first install takes about 15 minutes. Adding HTTPS, email and backups usually takes another hour.
Can I self-host Supabase on a 2 GB VPS?
No. The official minimum is 4 GB of RAM and 2 CPU cores, and 8 GB or more is recommended. A 2 GB server will run out of memory.
Is self-hosted Supabase the same as Supabase Cloud?
The core services are the same, but the hosted platform adds managed backups, automatic updates and a managed dashboard, so on your own server you handle those yourself.
Do I need Kubernetes to self-host Supabase?
No. Docker Compose on a single VPS is the official and simplest way to get started.
How do I back up self-hosted Supabase?
Dump Postgres from the database container with pg_dumpall on a schedule, back up the project folder and storage volume, and copy the files off the server. Step 10 shows the exact script.
Why are my emails not sending?
Self-hosted Supabase needs a real SMTP server. Add your provider details in the .env file and recreate the containers.
Final Thoughts
Self-hosting Supabase on a VPS gives you full control over your backend, a clear server bill and the freedom to choose where your data lives. The steps are simple, but the details decide whether it stays safe: change every default secret, put HTTPS in front, close the extra ports, and keep tested backups. Start with a server that meets the official requirements, and you can scale it up as your app grows.
