We buy the servers we test with our own money. Some links are affiliate links; they never change a verdict. Disclosure · How we test
For a Supabase self-host VPS, 4 GB of RAM is the real minimum and 8 GB is comfortable. We ran the official Supabase Docker Compose stack on five Hetzner servers. After 90 seconds idle, the whole system used 1,594 MiB on the 4 GB CX23 and 1,732 MiB on the 8 GB CX33, with all 11 containers healthy on every server. The images alone take about 9.6 to 10.1 GB of disk.
This matters because most guides quote requirement tables without running anything, and because Hetzner repriced its cloud plans in 2026. Here is what the stack actually used, and which size to buy.
Verdict
Buy the Hetzner CX33 (4 vCPU, 8 GB, 10.27 € a month) for a real project: Supabase idled at 1,732 MiB there, leaving about 6 GB for data, traffic and other apps. The CX23 (4 GB, 6.64 €) runs the stack too, but it is a test or hobby box.
Tested in the Lab Hetzner CX23, CX33, CX43, CAX11, CAX21 · Nov 2026
This page is part of our Supabase hosting section. If you are deciding between running it yourself and paying Supabase, see Supabase self-hosted vs cloud cost.
What we ran
On 5 November 2026 we used fresh Hetzner Cloud servers in Helsinki with Ubuntu 24.04. Our benchmark script cloned the official Supabase repository, copied the example environment file and started the default stack. These are the exact lines from lab/bench.sh:
apt-get -y -qq install docker.io docker-compose-v2
systemctl enable --now docker
git clone -q --depth 1 https://github.com/supabase/supabase sb
cd sb/docker && cp .env.example .env
docker compose pull -q
docker compose up -d
sleep 90
docker stats --no-stream --format '{{.Name}};{{.MemUsage}}'
docker compose down -v
Two things to know about this test. First, it ran with the demo secrets from .env.example, on throwaway servers, and was torn down with docker compose down -v right after measuring. Never do that on a server you keep (see the security section). Second, it measures an idle stack: no users, no data, no requests. Your RAM use goes up with real traffic and a growing database. We have not load-tested Supabase yet.
The default stack started 11 containers. Supabase's docs list the default services as Studio (the dashboard), an API gateway, Auth (GoTrue), PostgREST, Realtime, Storage, imgproxy, postgres-meta, Postgres, Edge Runtime (for edge functions) and Supavisor (connection pooler). Logs and Analytics (Logflare and Vector) are an opt-in extra that the docs say increases resource use. Note that the current docs name Envoy as the default gateway, with Kong as an optional override; older guides show Kong.
The measurements
| Server | Containers | RAM (containers) | RAM used (system) | Fits? | Image pull | Disk (images) |
|---|---|---|---|---|---|---|
| Hetzner CX232 vCPU · 4 GB · x86_64 | 11 | 1,399 MiB | 1,594 MiB | yes | 111 s | 9.563GB |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 11 | 1,316 MiB | 1,732 MiB | yes | 50 s | 9.563GB |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 11 | 1,101 MiB | 1,870 MiB | yes | 29 s | 9.563GB |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 11 | 1,562 MiB | 1,564 MiB | yes | 99 s | 10.14GB |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 11 | 1,318 MiB | 1,712 MiB | yes | 52 s | 10.14GB |
Measured by AI Hosting Lab on 2026-11-05 · 5 servers · method · raw data
How to read it. RAM (containers) is the sum of docker stats for all 11 containers. RAM used (system) is the whole server, including Ubuntu and Docker, from free -m. MiB is mebibytes (1 MiB = 1,048,576 bytes, about 5% more than a megabyte). Image pull is how long docker compose pull took; Disk (images) is what the images take once pulled.
Facts that stand out:
- Every server ran the full stack with 0 unhealthy containers, including the 2 vCPU, 4 GB CX23 and CAX11.
- Idle RAM was similar everywhere: 1,564 MiB (CAX11) to 1,870 MiB (CX43) for the whole system. More RAM did not mean much more use at idle.
- Pull time is where size shows. The CX23 needed 110.7 s, the CX33 49.6 s, the CX43 29.2 s. Pulling also unpacks images, which needs CPU and disk.
- ARM images are bigger: 10.14 GB against 9.563 GB on x86.
docker compose upuntil the containers reported healthy took 31.5 s on the CX23 and 18.8 s on the CX33.
Comparison: which size for whom
| Server | vCPU / RAM | Price / month | System RAM used, idle | RAM left, idle | Disk | Our call |
|---|---|---|---|---|---|---|
| Hetzner CX23 | 2 / 4 GB, x86 | 6.64 € | 1,594 MiB | about 2.2 GB | 38G | Minimum: tests, hobby |
| Hetzner CAX11 | 2 / 4 GB, ARM | 7.25 € | 1,564 MiB | about 2.2 GB | 38G | Minimum on ARM |
| Hetzner CX33 | 4 / 8 GB, x86 | 10.27 € | 1,732 MiB | about 5.9 GB | 75G | Comfortable: best value |
| Hetzner CAX21 | 4 / 8 GB, ARM | 12.69 € | 1,712 MiB | about 5.9 GB | 75G | Comfortable on ARM |
| Hetzner CX43 | 8 / 16 GB, x86 | 19.35 € | 1,870 MiB | about 13.4 GB | 150G | Supabase plus heavy extras |
"RAM left" is total RAM minus system RAM used at idle, our arithmetic. Prices are Hetzner gross monthly prices from the Hetzner Cloud API, checked 5 November 2026.
Hetzner CX23: the minimum
2 vCPU, 4 GB, 6.64 € a month. Best for: trying Supabase, a side project with a few users, a staging copy. Main drawback: about 2.2 GB free at idle, and the slowest pull (110.7 s) and start (31.5 s) of the group. The 38G disk loses about a quarter to the images before you store anything. Skip it if: you plan to run anything else on the same server, or you expect the database to grow past a few GB.
Hetzner CAX11: the ARM minimum
2 vCPU ARM, 4 GB, 7.25 €. Best for: the same small use as the CX23 if you prefer ARM. Main drawback: costs more than the CX23 for the same RAM, and its images are bigger (10.14 GB). Skip it if: price is your main reason; the CX23 is cheaper.
Hetzner CX33: the comfortable choice
4 vCPU, 8 GB, 10.27 €. Best for: a real app with real users, or Supabase next to a small n8n instance. Pull took 49.6 s and start 18.8 s. Main drawback: none that showed in our idle test; we have not measured it under load. Skip it if: you also want a local LLM on the same server; check that with the VPS RAM calculator first.
Hetzner CAX21: comfortable on ARM
4 vCPU ARM, 8 GB, 12.69 €. Best for: people already on ARM. All 11 containers ran healthy. Main drawback: 2.42 € a month more than the CX33 for the same RAM, with a similar pull time (52.3 s). Skip it if: you have no reason to choose ARM. See Hetzner CX vs CAX.
Hetzner CX43: room for everything
8 vCPU, 16 GB, 19.35 €. Best for: Supabase plus other services on one box, or a large database. Fastest pull (29.2 s). Main drawback: at idle Supabase used only 1,870 MiB here, so most of the RAM waits for other work. Skip it if: Supabase is the only thing you run.
If you want Hetzner Cloud, the CX33 is the one we would pick. Hetzner pays us no commission. We have not tested other providers in the Lab yet (Hostinger, DigitalOcean, Vultr and others are scheduled), so we make no performance claims for them. Our Hetzner alternatives page lists them.
Our numbers vs the official requirements
Supabase's Docker guide lists a minimum of 4 GB RAM, 2 CPU cores and 40 GB SSD, and recommends 8 GB+, 4 cores+ and 80 GB+ SSD. Our measurements back that up. The 4 GB minimum works, and the stack fits with room to spare at idle. The 40 GB disk minimum is tight, because the images alone took 9.563 GB on x86 and Hetzner's 40 GB plans showed 38G usable. The docs also say you can remove unused services (Realtime, Storage, imgproxy, Edge Runtime) from docker-compose.yml to lower the requirements. We measured only the full default stack.
What self-hosted Supabase lacks compared with Supabase Cloud
From Supabase's own self-hosting overview, these platform features are not available when you self-host:
- Branching
- Managed backups and point-in-time recovery (PITR)
- Advanced metrics beyond logs
- Analytics and vector buckets
- ETL
- The Management API
- Multiple organizations and projects in Studio: "Self-hosted Supabase runs as a single project"
The same page says self-hosted Supabase is community-supported, and lists what becomes your job: server provisioning and maintenance, security hardening and updates, Postgres maintenance, high availability and scaling, backups and disaster recovery, monitoring and uptime. API keys live in your .env file and are rotated there, not in a dashboard. Logs and Analytics are off by default.
Updates are your job too. The docs say stable self-hosted snapshots come out about once a month and are applied with the bundled update.sh script.
Security: what to change before you start
Replace every default secret
The official docker/.env.example ships with placeholder secrets, for example:
POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password
JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long
DASHBOARD_USERNAME=supabase
DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated
It also contains ready-made ANON_KEY and SERVICE_ROLE_KEY values, plus SECRET_KEY_BASE and VAULT_ENC_KEY placeholders. The file itself says: "YOU MUST CHANGE ALL THE DEFAULT VALUES BELOW BEFORE STARTING THE CONTAINERS FOR THE FIRST TIME". The Docker guide says you should never start self-hosted Supabase with these defaults, and recommends generating keys with the scripts in its utils/ folder (generate-keys.sh and add-new-auth-keys.sh) as the first step. Those demo values are public, so anyone who has read the example file holds the same keys.
Protect Studio and use HTTPS
By default the API gateway listens on port 8000 and Studio is reachable at http://<your-domain>:8000, protected by HTTP basic auth with DASHBOARD_USERNAME and DASHBOARD_PASSWORD. The docs recommend HTTPS through a reverse proxy such as Caddy or Nginx on port 443 for production, and a secrets manager instead of a plain .env. We run Caddy in front of our own n8n server; we have not yet run Supabase behind it in the Lab.
Do not trust ufw alone
Docker's documentation warns that traffic to published container ports "gets diverted before it goes through the ufw firewall settings". If Supabase publishes a port, a ufw deny rule will not block it. Either keep ports bound to localhost behind your reverse proxy, or block them with a firewall that sits in front of the server.
Harden SSH like any VPS
This is the SSH part of the hardening we ran on our own n8n server (lab/configs/hardening.sh), which applies to a Supabase box as well:
cat > /etc/ssh/sshd_config.d/10-lab-hardening.conf <<CONF
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
CONF
sshd -t
systemctl reload ssh 2>/dev/null || echo "ssh.socket activation: config applies to new connections"
A gotcha we hit: on Ubuntu 24.04 and newer, sshd starts through ssh.socket, so systemctl reload ssh fails with "ssh.service is not active". New connections already use the new config. Test your key login in a second terminal before you close the first. The full checklist is in how to secure an Ubuntu VPS.
Plan backups from day one
Without managed backups or PITR, your data is only as safe as the last copy you made off the server. Schedule database dumps and copy them somewhere else before you put real users on it.
Before you buy: a short sizing checklist
- Count everything on the box. Supabase idled at 1,594 to 1,870 MiB of system RAM in our tests. If n8n runs next to it, our VPS RAM calculator puts n8n plus Supabase at about 3.0 GB, which technically fits 4 GB but leaves little room once real data arrives.
- Budget disk for images twice. An update pulls new images before old ones are removed, so keep free space for roughly a second set of about 9.6 GB (x86) or 10.1 GB (ARM) on top of your data, until you prune the old ones.
- Pick the architecture once. ARM ran every container in our test, but if you later add images that only exist for x86, moving is work. If you have no reason to choose ARM, the x86 CX33 was also cheaper.
- Decide where backups go before the first user signs up, since there are no managed backups self-hosted.
- Start smaller than you fear. At idle the CX43 used only 138 MiB more than the CX33 for the same stack. Start on the CX33 and move up when your own monitoring shows real pressure.
Next step: compare what this costs you per month, including upkeep time, against Supabase's own plans in Supabase self-hosted vs cloud cost.
Hetzner prices on this page include 21% VAT, as charged to our Czech (EU consumer) account by the Hetzner API on 2026-11-05. Without VAT (businesses, most buyers outside the EU): CX23 5.49 €, CX33 8.49 €, CX43 15.99 €, CAX11 5.99 €, CAX21 10.49 € per month.
FAQ
How much RAM does self-hosted Supabase need?
On our Hetzner servers, the 11 containers of the official Docker Compose stack used between 1,101 and 1,562 MiB after 90 seconds idle, and the whole system used 1,564 to 1,870 MiB. A 4 GB server runs it; 8 GB leaves room for real data and other apps.
What is the cheapest VPS that can run Supabase?
In our tests the Hetzner CX23 (2 vCPU, 4 GB, 6.64 € a month) ran all 11 containers with none unhealthy. We treat it as the minimum for testing and small projects, and the CX33 (4 vCPU, 8 GB, 10.27 €) as the comfortable choice.
Does Supabase run on ARM servers?
Yes. On the ARM CAX11 and CAX21 all 11 containers came up healthy. The ARM images took 10.14 GB of disk against 9.563 GB on x86.
What does self-hosted Supabase not include?
Supabase's docs list branching, managed backups and point-in-time recovery, advanced metrics, analytics and vector buckets, ETL, the Management API, and multiple organizations and projects in Studio as not available when self-hosting.
Is it safe to start with the default .env.example?
No. The file says "YOU MUST CHANGE ALL THE DEFAULT VALUES BELOW BEFORE STARTING THE CONTAINERS FOR THE FIRST TIME", and the docs say never to start self-hosted Supabase with those defaults.

