Deploying Self-Hosted Supabase on Azure: A Complete Guide

Deploy self-hosted Supabase on Microsoft Azure step by step: VM sizing, NSG rules, Docker setup, SSL, and the Azure-specific gotchas nobody warns you about.

Cover Image for Deploying Self-Hosted Supabase on Azure: A Complete Guide

We've covered deploying self-hosted Supabase on AWS EC2 and Google Cloud, which leaves the third member of the big three: Microsoft Azure. If your company already lives in the Microsoft ecosystem — Entra ID for identity, Azure credits from a startup program, or a compliance team that has already approved Azure as a vendor — running Supabase there is often the path of least resistance, even if a budget VPS provider would be cheaper per gigabyte of RAM.

This guide walks through the full deployment: picking a VM size that won't fall over, configuring network security groups, installing the Supabase stack with Docker, and the Azure-specific quirks — burstable CPU credits, Blob Storage's missing S3 API — that trip people up. By the end you'll have a production-ready instance you can point a custom domain at.

Why Azure (and Why Maybe Not)

Let's be honest about the trade-offs first, because Azure is rarely the cheapest way to self-host Supabase.

Reasons Azure makes sense:

  • You have credits. Microsoft for Startups hands out up to $150k in Azure credits. Free compute changes the math entirely.
  • Your org is already there. If procurement has approved Azure and your VNet, monitoring, and identity story all live there, adding one more vendor for a database is friction you don't need.
  • Compliance and data residency. Azure has more regions than any other cloud, which matters if you need your data in a specific jurisdiction. Pair this with self-hosting and you control exactly where every byte lives.
  • Entra ID integration. If your users sign in with Microsoft accounts, you're already halfway to configuring Azure login for your Supabase instance.

Reasons to look elsewhere:

  • Price. A 2 vCPU / 8 GB burstable VM (B2as v2) runs about $0.075/hour — roughly $55/month before disk and bandwidth. Hetzner gives you similar specs for around €7/month. You're paying a 5-7x premium for the Azure logo.
  • Egress fees. Azure charges for outbound data after the first 100 GB/month. A chatty Realtime app or heavy Storage downloads will show up on your bill.
  • Complexity. Azure's portal and terminology (resource groups, NSGs, managed disks with four performance tiers) have a steeper learning curve than a VPS dashboard.

If none of the "reasons for" apply to you, read our cost breakdown of self-hosting Supabase before committing. If they do apply, carry on.

Choosing a VM Size

The full Supabase stack — Postgres, GoTrue, PostgREST, Realtime, Storage, Kong, Studio, and friends — needs about 4 GB of RAM to run comfortably and 8 GB to run well. Check the system requirements before provisioning.

VM SizevCPU / RAM~Monthly (Linux, pay-as-you-go)Verdict
B2s2 / 4 GB~$30Works for dev/staging; tight for production
B2as v22 / 8 GB~$55Sweet spot for most projects
B2ms2 / 8 GB~$60Older gen; pick B2as v2 instead
D2as v52 / 8 GB~$70Non-burstable; for sustained CPU load

One Azure-specific warning: the entire B-series is burstable. You accumulate CPU credits while idle and spend them under load. For a typical CRUD app this is fine — databases idle a lot. But if you run sustained workloads (heavy Realtime fan-out, frequent analytical queries, busy Edge Functions), you can exhaust your credits and get throttled to a fraction of a core, at which point everything gets slow in a way that's confusing to debug. There's a long-running Supabase discussion on Azure performance where under-provisioned burstable VMs are a recurring theme. If your CPU baseline sits above ~40%, pay for the D-series.

For disk, skip the default. Attach a Premium SSD (P10, 128 GB) or at minimum a Standard SSD as your data disk. Postgres on Azure's Standard HDD tier is an exercise in patience.

Step 1: Provision the VM

Using the Azure CLI (portal works too, but this is reproducible):

az group create --name supabase-rg --location eastus

az vm create \
  --resource-group supabase-rg \
  --name supabase-vm \
  --image Ubuntu2404 \
  --size Standard_B2as_v2 \
  --admin-username azureuser \
  --generate-ssh-keys \
  --os-disk-size-gb 64 \
  --public-ip-sku Standard

Attach a dedicated data disk for Postgres:

az vm disk attach \
  --resource-group supabase-rg \
  --vm-name supabase-vm \
  --name supabase-data \
  --new --size-gb 128 --sku Premium_LRS

Step 2: Lock Down the Network Security Group

Azure's NSG is your firewall. Open only what you need:

# SSH — restrict to your IP, not the internet
az network nsg rule create -g supabase-rg --nsg-name supabase-vmNSG \
  -n allow-ssh --priority 100 --source-address-prefixes <YOUR_IP>/32 \
  --destination-port-ranges 22 --access Allow --protocol Tcp

# HTTPS for the API gateway and Studio (behind a reverse proxy)
az network nsg rule create -g supabase-rg --nsg-name supabase-vmNSG \
  -n allow-https --priority 110 --source-address-prefixes '*' \
  --destination-port-ranges 80 443 --access Allow --protocol Tcp

Do not open 5432 (Postgres), 8000 (Kong), or 3000 (Studio) to the internet. Everything public should flow through a reverse proxy on 443. Studio in particular has no built-in authentication beyond basic auth — treat it like an admin panel, because it is one.

Step 3: Install Docker and the Supabase Stack

SSH in, then:

# Docker
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER && newgrp docker

# Format and mount the data disk (device name may vary — check lsblk)
sudo mkfs.ext4 /dev/sdc
sudo mkdir /data && sudo mount /dev/sdc /data
echo '/dev/sdc /data ext4 defaults,nofail 0 2' | sudo tee -a /etc/fstab

# Supabase
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env

Now the part everyone rushes: secrets. Generate real values for POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, and DASHBOARD_PASSWORD. Set API_EXTERNAL_URL and SITE_URL to your eventual public domain — recent stack updates changed how the default URL is handled, and auth redirects will silently misbehave if these are wrong. Our environment variables guide covers every value in the file.

Point the Postgres volume at your Premium SSD by editing the db service volume in docker-compose.yml to use /data/postgres, then:

docker compose up -d
docker compose ps   # everything should be running/healthy

For hardening beyond the defaults — resource limits, log rotation, restart policies — see our production Docker Compose best practices.

Step 4: Domain, SSL, and the Blob Storage Gotcha

Point an A record at your VM's public IP (consider making the IP static first: az network public-ip update --allocation-method Static). Then put Caddy or Nginx in front of Kong for automatic Let's Encrypt certificates — or skip the manual proxy work entirely and use Supascale's domain binding, which provisions SSL automatically.

Two Azure-specific gotchas worth knowing before you go live:

  1. Azure Blob Storage doesn't speak S3. Supabase Storage's external backend and most Postgres backup tooling expect an S3-compatible API, which Blob Storage doesn't natively provide. Your realistic options: keep Storage on the local file backend (and size your disk accordingly), run MinIO as an S3 gateway, or use an S3-compatible service like Cloudflare R2 for backup storage. Don't discover this during your first restore.
  2. Deallocate ≠ stop. Stopping a VM from inside the OS still bills you for compute. Only az vm deallocate stops the meter. Relevant for staging environments you shut down at night.

Managing It After Day One

Getting Supabase running on Azure is a weekend project. Keeping it running — scheduled backups, restore testing, SSL renewals, version upgrades, monitoring — is the part that turns into a recurring tax on your time.

That operational layer is what Supascale handles: automated S3-compatible backups with one-click restore, custom domains with managed SSL, OAuth provider configuration through a UI instead of .env archaeology, and selective service deployment so your 8 GB VM isn't running services you don't use. It's a one-time license — from $99, unlimited projects — not another monthly subscription stacked on top of your Azure bill.

Wrapping Up

Azure is a solid home for self-hosted Supabase when credits, compliance, or an existing Microsoft footprint tip the scales — just go in with clear eyes: pick B2as v2 or larger, put Postgres on a Premium SSD, keep every port except 443 closed, watch your burstable CPU credits, and solve the S3-compatibility question before you need a backup. The stack itself runs the same on Azure as anywhere else; it's the edges — networking, storage APIs, billing — where the platform specifics live.

Further Reading