{"id":24322,"date":"2026-11-11T12:41:35","date_gmt":"2026-11-11T07:11:35","guid":{"rendered":"https:\/\/www.youstable.com\/blog\/?p=24322"},"modified":"2026-11-11T12:46:53","modified_gmt":"2026-11-11T07:16:53","slug":"how-to-self-host-supabase-on-a-vps","status":"publish","type":"post","link":"https:\/\/www.youstable.com\/blog\/how-to-self-host-supabase-on-a-vps\/","title":{"rendered":"How to Self-Host Supabase on a VPS in 2026: Step by Step"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>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 <code>.env<\/code> file, and a reverse proxy such as Caddy for HTTPS.<\/strong> You copy the files, replace every default secret, run <code>docker compose up -d<\/code>, and Supabase Studio is live in about 15 minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"what-does-it-mean-to-self-host-supabase\">What Does It Mean to Self-Host Supabase?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"what-you-need-before-you-start\">What You Need Before You Start<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>A VPS running Ubuntu 22.04 or 24.04<\/strong> with root or sudo access.<\/li>\n\n\n<li><strong>A domain or subdomain<\/strong> such as <code>api.yourdomain.com<\/code> pointed at the server IP, needed for HTTPS in production.<\/li>\n\n\n<li><strong>An SMTP account<\/strong> from any email provider, so sign-up and password reset emails can be delivered.<\/li>\n\n\n<li><strong>Basic terminal skills:<\/strong> connecting over SSH and editing a file with nano.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"how-much-server-do-you-need-for-supabase\">How Much Server Do You Need for Supabase?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Level<\/th><th>RAM<\/th><th>CPU<\/th><th>Disk<\/th><\/tr><\/thead><tbody><tr><td>Minimum<\/td><td>4 GB<\/td><td>2 cores<\/td><td>40 GB SSD<\/td><\/tr><tr><td>Recommended<\/td><td>8 GB or more<\/td><td>4 cores or more<\/td><td>80 GB or more SSD<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">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 <a href=\"https:\/\/www.youstable.com\/vps-hosting\/supabase\">Supabase VPS hosting<\/a> page shows which plan fits which workload and the locations available in India, the USA and the Netherlands.<\/p>\n\n\n\n<div class=\"wp-block-group has-white-color has-text-color has-background is-layout-constrained wp-container-core-group-is-layout-71818893 wp-block-group-is-layout-constrained\" style=\"border-radius:12px;background-color:#0e1a47;padding-top:28px;padding-right:28px;padding-bottom:28px;padding-left:28px\">\n<h3 class=\"wp-block-heading has-text-color\" style=\"color:#ffffff\" class=\"wp-block-heading has-text-color\" style=\"color:#ffffff\" id=\"need-a-server-that-fits-supabase\">Need a Server That Fits Supabase?<\/h3>\n\n\n\n<p class=\"has-text-color wp-block-paragraph\" style=\"color:#ffffff\">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.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-color has-background wp-element-button\" href=\"https:\/\/www.youstable.com\/vps-hosting\/supabase\" style=\"border-radius:50px;color:#0e1a47;background-color:#f7a51b\"><strong>See Supabase VPS Plans<\/strong><\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-1-connect-to-the-vps-and-update-ubuntu\">Step 1: Connect to the VPS and Update Ubuntu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Log in over SSH, then update the system packages and create a working user if you do not want to run everything as root.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh root@YOUR_SERVER_IP\napt update &amp;&amp; apt upgrade -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reboot if the upgrade installed a new kernel, then reconnect.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-2-install-docker-and-docker-compose\">Step 2: Install Docker and Docker Compose<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsSL https:\/\/get.docker.com | sh\ndocker --version\ndocker compose version<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both commands should print a version number. If you want a deeper look at running containers on a server, see how a <a href=\"https:\/\/www.youstable.com\/vps-hosting\/docker\">Docker VPS<\/a> is set up and sized.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-3-download-the-official-supabase-docker-files\">Step 3: Download the Official Supabase Docker Files<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Clone the Supabase repository, then copy only its <code>docker<\/code> folder and the example environment file into a project directory. Keeping your project separate from the clone makes later updates easier.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone --depth 1 https:\/\/github.com\/supabase\/supabase\nmkdir supabase-project\ncp -rf supabase\/docker\/* supabase-project\ncp supabase\/docker\/.env.example supabase-project\/.env\ncd supabase-project<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The folder now contains <code>docker-compose.yml<\/code>, the <code>.env<\/code> file and a few helper folders for volumes and configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-4-replace-every-default-secret\">Step 4: Replace Every Default Secret<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the most important step. The example <code>.env<\/code> 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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the file with <code>nano .env<\/code> and change these values:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>POSTGRES_PASSWORD<\/code>: a long random password for the database.<\/li>\n\n\n<li><code>JWT_SECRET<\/code>: a random string of at least 32 characters. Every token is signed with it.<\/li>\n\n\n<li><code>ANON_KEY<\/code> and <code>SERVICE_ROLE_KEY<\/code>: API keys that must be generated from your JWT secret.<\/li>\n\n\n<li><code>DASHBOARD_USERNAME<\/code> and <code>DASHBOARD_PASSWORD<\/code>: the login for Supabase Studio.<\/li>\n\n\n<li><code>SECRET_KEY_BASE<\/code>, <code>VAULT_ENC_KEY<\/code> and <code>PG_META_CRYPTO_KEY<\/code>: random strings used for internal encryption.<\/li>\n\n\n<li><code>POOLER_TENANT_ID<\/code>: any short unique name for the connection pooler.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You can create random values with <code>openssl rand -hex 32<\/code>. Newer versions of the repository also include a key helper in the <code>utils<\/code> folder, so check for it first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls utils\nsh .\/utils\/generate-keys.sh<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the helper is not there, generate a 32-plus character <code>JWT_SECRET<\/code> yourself, then create the <code>ANON_KEY<\/code> and <code>SERVICE_ROLE_KEY<\/code> as JWT tokens signed with that secret, using the <code>anon<\/code> and <code>service_role<\/code> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-5-set-your-urls-in-the-env-file\">Step 5: Set Your URLs in the .env File<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SUPABASE_PUBLIC_URL=https:\/\/api.yourdomain.com\nAPI_EXTERNAL_URL=https:\/\/api.yourdomain.com\nSITE_URL=https:\/\/yourapp.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>SITE_URL<\/code> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-6-start-supabase\">Step 6: Start Supabase<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pull the images, then start every service in the background.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker compose pull\ndocker compose up -d\ndocker compose ps<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first pull takes a few minutes. When <code>docker compose ps<\/code> shows the containers as running or healthy, the stack is up. If one keeps restarting, read its log with <code>docker compose logs db<\/code> or the name of the service that failed. Most first-start problems are a weak or badly formatted value in the <code>.env<\/code> file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Supabase Studio and the API now answer on port 8000 of your server. Open <code>http:\/\/YOUR_SERVER_IP:8000<\/code>, sign in with the dashboard username and password you set, and you will see the Studio dashboard. Test the API with your anon key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl http:\/\/localhost:8000\/rest\/v1\/ -H \"apikey: YOUR_ANON_KEY\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-7-add-a-domain-and-https-with-caddy\">Step 7: Add a Domain and HTTPS With Caddy<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First create a DNS <strong>A record<\/strong> that points <code>api.yourdomain.com<\/code> to your server IP. Then install Caddy and write its config:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apt install -y debian-keyring debian-archive-keyring apt-transport-https curl\napt install -y caddy\n\nnano \/etc\/caddy\/Caddyfile<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>api.yourdomain.com {\n    reverse_proxy localhost:8000\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl reload caddy<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Within a minute, <code>https:\/\/api.yourdomain.com<\/code> loads Studio with a valid certificate. If you installed Nginx instead, the idea is the same: proxy the domain to <code>localhost:8000<\/code> and add a certificate with Certbot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-8-configure-email-for-sign-ups-and-password-resets\">Step 8: Configure Email for Sign-Ups and Password Resets<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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 <code>.env<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SMTP_ADMIN_EMAIL=admin@yourdomain.com\nSMTP_HOST=smtp.yourprovider.com\nSMTP_PORT=587\nSMTP_USER=your-smtp-username\nSMTP_PASS=your-smtp-password\nSMTP_SENDER_NAME=Your App<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply the change by recreating the containers, then sign up a test user and confirm the email arrives.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker compose up -d<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-9-lock-down-the-ports\">Step 9: Lock Down the Ports<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A common mistake is leaving database and admin ports open to the whole internet. Allow only what you need through the firewall:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ufw allow OpenSSH\nufw allow 80\nufw allow 443\nufw enable<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">There is one catch. Docker publishes container ports by writing its own firewall rules, so a port listed in <code>docker-compose.yml<\/code> 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 <code>127.0.0.1:8000:8000<\/code>, and review the Postgres and pooler port mappings the same way unless you truly need outside database access. Then run <code>docker compose up -d<\/code> again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-10-schedule-database-backups\">Step 10: Schedule Database Backups<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p \/root\/backups\nnano \/root\/backup-supabase.sh<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\nset -e\nDIR=\/root\/backups\nFILE=$DIR\/supabase-$(date +%F).sql.gz\ndocker exec supabase-db pg_dumpall -U postgres | gzip &gt; \"$FILE\"\nfind $DIR -name 'supabase-*.sql.gz' -mtime +7 -delete<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod +x \/root\/backup-supabase.sh\ncrontab -e\n# add this line to run every night at 2 AM:\n0 2 * * * \/root\/backup-supabase.sh<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Also back up the project folder, because it holds your <code>.env<\/code> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"step-11-update-supabase-safely\">Step 11: Update Supabase Safely<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/supabase-project\ndocker compose pull\ndocker compose down\ndocker compose up -d<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Update during a quiet hour, and keep the previous <code>docker-compose.yml<\/code> and <code>.env<\/code> so you can roll back. Do not upgrade production blindly: try the new version on a staging VPS first.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"common-problems-and-fixes\">Common Problems and Fixes<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Problem<\/th><th>Likely cause<\/th><th>Fix<\/th><\/tr><\/thead><tbody><tr><td>A container keeps restarting<\/td><td>Bad or short value in the .env file<\/td><td>Check logs with docker compose logs SERVICE and correct the value<\/td><\/tr><tr><td>Out of memory, services killed<\/td><td>Server too small for the stack<\/td><td>Move to a plan with 8 GB RAM or more, or add swap while you resize<\/td><\/tr><tr><td>Studio opens but the API returns 401<\/td><td>Wrong anon key or JWT secret mismatch<\/td><td>Regenerate both keys from the same JWT secret and recreate containers<\/td><\/tr><tr><td>No confirmation emails arrive<\/td><td>SMTP not configured<\/td><td>Set the SMTP values in .env and run docker compose up -d<\/td><\/tr><tr><td>HTTPS certificate fails<\/td><td>DNS not pointing to the server yet<\/td><td>Check the A record, wait for it to propagate, then reload Caddy<\/td><\/tr><tr><td>Login redirects to localhost<\/td><td>SITE_URL or API_EXTERNAL_URL still default<\/td><td>Set both to your real URLs and recreate the containers<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"which-vps-should-you-use-for-self-hosted-supabase\">Which VPS Should You Use for Self-Hosted Supabase?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 <a href=\"https:\/\/www.youstable.com\/vps-hosting\/\">VPS hosting plans<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"faqs\">FAQs<\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-supabase-1\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"is-supabase-free-to-self-host\">Is Supabase free to self-host?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. Supabase is open source, so the software is free. You pay only for the server, your domain and any email service.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-2\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"how-long-does-a-supabase-self-host-install-take\">How long does a Supabase self-host install take?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>The official guide says a first install takes about 15 minutes. Adding HTTPS, email and backups usually takes another hour.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-3\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"can-i-self-host-supabase-on-a-2-gb-vps\">Can I self-host Supabase on a 2 GB VPS?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>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.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-4\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"is-self-hosted-supabase-the-same-as-supabase-cloud\">Is self-hosted Supabase the same as Supabase Cloud?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>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.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-5\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"do-i-need-kubernetes-to-self-host-supabase\">Do I need Kubernetes to self-host Supabase?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. Docker Compose on a single VPS is the official and simplest way to get started.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-6\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"how-do-i-back-up-self-hosted-supabase\">How do I back up self-hosted Supabase?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>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.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-supabase-7\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \" class=\"rank-math-question \" id=\"why-are-my-emails-not-sending\">Why are my emails not sending?<\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Self-hosted Supabase needs a real SMTP server. Add your provider details in the .env file and recreate the containers.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"final-thoughts\">Final Thoughts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n","protected":false},"excerpt":{"rendered":"<p>To self-host Supabase on a VPS, you need an Ubuntu server with at least 4 GB of RAM (8 GB [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":24324,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"iawp_total_views":1,"footnotes":""},"categories":[1136],"tags":[],"class_list":["post-24322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/24322","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/comments?post=24322"}],"version-history":[{"count":2,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/24322\/revisions"}],"predecessor-version":[{"id":24329,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/posts\/24322\/revisions\/24329"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/media\/24324"}],"wp:attachment":[{"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/media?parent=24322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/categories?post=24322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.youstable.com\/blog\/wp-json\/wp\/v2\/tags?post=24322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}