Air-Gapped Self-Hosted Supabase: Offline Deployment Guide

Deploy self-hosted Supabase in air-gapped environments: mirror Docker images, handle auth without OAuth, and run offline updates and internal S3 backups.

Cover Image for Air-Gapped Self-Hosted Supabase: Offline Deployment Guide

Most self-hosted Supabase guides quietly assume your server can reach the internet. docker compose pull grabs images from Docker Hub, Let's Encrypt validates your domain over port 80, GoTrue sends emails through an external SMTP relay, and OAuth logins round-trip through Google's servers. In an air-gapped environment — a defense network, a hospital data center, an industrial site, a bank's isolated segment — every one of those assumptions breaks.

The good news: Supabase is one of the few backend platforms that can run with zero internet access, because the entire stack is just containers and Postgres. The standard installation process gets you most of the way; the rest is knowing which external dependencies to cut and what to replace them with. This guide walks through exactly that: mirroring the images, reworking auth and email, handling SSL with an internal CA, and keeping updates and backups running when nothing can phone home.

First, decide if you actually need air-gapped

An honest word before the tutorial: a true air gap is the most expensive deployment topology you can choose. Every update becomes a physical or gateway-mediated transfer, every debugging session loses access to upstream images, and social OAuth is off the table entirely.

If your real requirement is "the database must not be reachable from the internet," you don't need an air gap — you need a firewall and a private overlay network. A locked-down VPS with Tailscale providing private network access achieves that with a fraction of the operational cost, and your servers can still pull images and certificates outbound.

Air-gapped deployment is for when the network itself is isolated by policy: classified environments, OT/industrial networks, or data residency and compliance regimes that mandate no external connectivity. If that's you, read on.

What breaks without internet access

Run the stock Supabase Docker Compose stack on an isolated network and here's what fails, roughly in order:

  1. Image pulls. docker compose up can't reach Docker Hub or public.ecr.aws. Nothing starts.
  2. SSL certificates. Let's Encrypt's HTTP-01 and DNS-01 challenges both require the outside world. ACME is dead on arrival.
  3. Email. GoTrue's signup confirmations, magic links, and password resets need SMTP. Resend, Postmark, and SES are unreachable.
  4. Social OAuth. Google, GitHub, and Discord logins require the browser and GoTrue to reach the provider. Neither can.
  5. Edge Functions imports. Deno resolves npm: and jsr: imports at runtime from public registries unless you vendor them.
  6. Analytics and version checks. Studio and some services attempt outbound telemetry and update checks. These fail gracefully, but they pollute your logs.

Each of these has a workable replacement. Let's go through them.

Step 1: Mirror the images

You need a machine with internet access (a staging host or build laptop) to prepare a transfer bundle. First, pin every image to an exact version — never latest in an air gap, because you can't re-pull to fix a surprise. This matters more than usual right now: Supabase made Envoy the default API gateway in August 2026, replacing Kong, and Postgres 17 became the default in June 2026 with an explicit warning against starting it on a Postgres 15 data directory. Your mirror list must match the compose file version you're actually deploying — see our Kong-to-Envoy migration prep guide for what changed.

On the connected host:

# List every image the stack needs
docker compose config --images > images.txt

# Pull and export them into a single archive
xargs -a images.txt -I{} docker pull {}
docker save $(cat images.txt | tr '\n' ' ') -o supabase-bundle.tar

Transfer supabase-bundle.tar across the gap (approved media, data diode, or gateway — whatever your policy allows), then on the isolated host:

docker load -i supabase-bundle.tar

For anything beyond a one-off deployment, run a private registry inside the gap instead — registry:2 or Harbor — and retag images against it in your compose file. That gives every internal host a consistent pull source and makes rollbacks a retag instead of another media transfer.

Check the system requirements before sizing the isolated host; you won't be able to casually resize a machine that lives behind a gap, so overprovision disk in particular.

Step 2: SSL with an internal CA

Forget ACME. Air-gapped environments use one of two approaches:

  • Enterprise CA: most organizations running air gaps already operate an internal PKI (Active Directory Certificate Services, or a Vault PKI engine). Issue a cert for your Supabase hostname and mount it into your reverse proxy.
  • Your own mini-CA: for smaller isolated networks, mkcert or a step-ca instance works fine. Distribute the root cert to every client machine that will talk to the API.

The reverse proxy configuration itself is identical to a connected deployment — only the certificate source changes. The client-side gotcha is real, though: every browser, mobile device, and CI runner inside the gap must trust your root CA, or supabase-js requests will fail TLS validation with errors that look exactly like the ones in our SSL troubleshooting guide.

Step 3: Auth without the outside world

This is the biggest functional trade-off. Your options, from simplest to most involved:

  • Email/password with an internal SMTP relay. Nearly every air-gapped org runs internal Exchange or a Postfix relay. Point GoTrue at it and confirmations, resets, and magic links all work normally — the flow is the same as configuring SMTP for any self-hosted instance, just with an internal host.
# .env — internal mail relay
SMTP_HOST=mail.internal.corp
SMTP_PORT=25
[email protected]
SMTP_SENDER_NAME="Internal Platform"
  • Internal OIDC. If the organization runs Keycloak, ADFS, or another identity provider inside the gap, wire it up as a custom OIDC provider. This is the best experience for enterprise users — single sign-on against the directory they already use, no external dependency.
  • Skip external social OAuth entirely. Google and GitHub login simply aren't possible. Don't try to proxy them; document it as a platform constraint.

Step 4: Edge Functions, updates, and backups

Edge Functions: vendor your dependencies. Run deno vendor (or cache imports into the function bundle) on the connected build host, and deploy the function with its dependency tree. A function that resolves npm:stripe at cold start will hang in an air gap.

Updates: treat upgrades as a pipeline, not an event. On the connected host: pull the new compose file, diff the image list, build a new bundle, and test the migration on a scratch instance before it crosses the gap. Our version upgrade guide covers the migration mechanics; the air-gapped addition is simply that your rollback plan can't include "pull the old image" — keep prior bundles on internal storage.

Backups: you can't ship backups to AWS S3, but you shouldn't be shipping them out anyway — that's usually the point of the gap. Run MinIO inside the isolated network as your S3-compatible target. The setup is identical to any S3-compatible storage backend, and Supascale's automated backups point at any S3 endpoint you give them, internal MinIO included. Test restores on schedule; in an air gap, nobody is coming to help if a backup turns out to be corrupt.

Where Supascale fits in an air gap

A management platform that requires a cloud connection would be useless here, which shaped how we built Supascale. The license is perpetual — one-time purchase from $99, and the version you own keeps working whether or not you ever renew updates. Backups target any S3-compatible endpoint, including internal MinIO. And selective service deployment matters more than usual in isolated environments: every container you don't run is one less image to mirror, patch, and justify to your security review. If your workload doesn't need Realtime or image transformation, don't ship them across the gap at all.

Conclusion

Air-gapped Supabase is entirely achievable: mirror pinned images through a private registry, issue certificates from an internal CA, route auth through internal SMTP or OIDC, vendor your Edge Function dependencies, and keep backups on in-gap S3 storage. The recurring theme is pre-staging — everything the stack would normally fetch on demand has to be brought inside deliberately, tested on a connected host first, and versioned so you can roll back without reaching out.

The trade-offs are real: no social OAuth, slower updates, and more ceremony around every change. But for the environments that need it, a full Postgres-backed platform with auth, storage, and APIs running entirely inside your perimeter is something very few backend stacks can offer at all.

Further Reading