[Guide] Supabase Self-Hosted using Orbstack HTTPS #34686
bradennapier
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
So I had setup with orbstack to take advanatage of.. well just that Orbstack is far superior in my eyes to Docker Desktop :-)
Anyway, I wanted to be certain the way i was setting things up was right and I still can not get the OpenAI integration to work properly as it says "invalid credentials" even though the API key is right... so in the end this guide just helped me polish a few points overall but I think it'd be helpful for anyone that is wanting similar!
Thought I'd share since I am paying $200/month for this thing .. might as well make it useful to as many people as possible!
It does a great job either way of breaking down how the self hosting works!
Overview
This guide explains how to run a self-hosted Supabase stack on OrbStack with a custom local domain and automatic HTTPS, closely mimicking a production setup. We will use OrbStack’s built-in wildcard domain support to expose Supabase’s API gateway (Kong) at
api.your-app.localover HTTPS. All Supabase services (PostgREST, Auth, Realtime, Storage, etc.) will be accessible through this single domain via Kong’s path-based routing (e.g./rest/v1/,/auth/v1/, etc.), just as in production. We’ll cover how to configure Docker Compose, environment variables, and certificates to achieve LAN-accessible, secure endpoints without CORS issues.OrbStack Domains and Automatic HTTPS
OrbStack automatically provides each container (or Compose service) with a local domain name under
.orb.localor even a custom such asapi.your-app.local. For Docker Compose projects, the pattern isservice.project.orb.localby default OrbStack docs. These domains are zero-config – OrbStack runs an internal reverse proxy that routes to the container, so you generally don’t need to publish ports or specify the host IP.Crucially, OrbStack can serve these domains over HTTPS with no manual certificate setup. On first use, OrbStack generates a local Certificate Authority and installs it on your Mac, then issues certificates for each container domain on the fly:
This means any container’s web service is reachable at
https://container-name.orb.localwith a trusted cert, no browser warnings! OrbStack even injects its root CA into containers for internal calls between containers over HTTPS.In our case, we want a clean domain (e.g.
api.your-app.local) rather than the defaultkong.project.orb.local. OrbStack supports custom domain mapping via container labels. We’ll assign the Kong service a custom domain and let OrbStack handle the DNS resolution and TLS. OrbStack’s proxy will detect the service’s web port and route traffic accordingly, so we can access our Supabase API athttps://api.your-app.localwith no port number needed example from the better stack guide.Why use OrbStack’s domain? This approach lets us avoid dealing with
localhost:<port>URLs and self-signed certs. Modern browsers treat.localdomains similar to localhost for security, and OrbStack’s automatic CA makes the connection secure out-of-the-box. This helps prevent CORS and mixed-content issues by serving the API over HTTPS on a consistent domain.Configuring Docker Compose for OrbStack
Supabase’s official
docker-compose.yml(in the Supabase GitHub) already defines all the services including Kong (the API gateway). By default, Kong’s container is namedsupabase-kong(service namekong) and it exposes port 8000 for HTTP and 8443 for HTTPS on the host github: supabase/docker-compose.yml.We will adjust this setup as follows:
Assign a custom domain to Kong: In the Compose file, add a label to the Kong service:
This tells OrbStack to associate the domain
api.your-app.localwith the Kong container. Once this is in place, any requests for*.api.your-app.localwill resolve to the Kong service example from the better stack guide. We choose “api” as the subdomain to mirror a production-like URL. (OrbStack requires custom domains to end in.local, which.your-app.localdoes.)Let OrbStack route HTTPS traffic: We want OrbStack’s proxy to handle TLS and forward to Kong’s HTTP port (8000). OrbStack automatically picks up standard web ports (80, 443, etc.) and common development ports to route traffic without specifying a port in the URL example from the better stack guide. Port 8000 is not a typical HTTP port, but OrbStack’s proxy can still use it if we specify it. Add another label on Kong:
This label designates Kong’s port 8000 as the container’s primary HTTP port for OrbStack’s routing. Now, when you open
https://api.your-app.local, OrbStack will terminate TLS and forward the request to Kong’s port 8000 internally (no port visible in the URL). If this label is omitted, OrbStack might still default to 8000 in this case, but it’s safer to be explicit, especially since Kong also listens on 8443. (OrbStack only proxies its own HTTPS on port 443 by default; hittingapi.your-app.local:8443directly isn’t handled by OrbStack’s cert generator github: orbstack issue #1165. The label ensures OrbStack uses 8000 for incoming HTTPS traffic onapi.your-app.localexample from the better stack guide.)Adjust port mappings (optional): The default compose maps
${KONG_HTTP_PORT}:8000and${KONG_HTTPS_PORT}:8443to the host github: supabase/docker-compose.yml. In the Supabase.env.example, these default to 8000 and 8443 github: supabase/.env.example. You can keep these mappings if you still want to access Kong vialocalhost:8000or8443. However, if you plan to use only the OrbStack domain, you could remove or change these mappings. For example, you might remove the8443:8443binding to avoid confusion (OrbStack’s proxy will be handling HTTPS on 443). It’s fine to leave the mappings as-is; they won’t interfere with OrbStack’s domain access. Just remember not to uselocalhost:8000in your app, use theapi.your-app.localdomain instead.Verify Kong service health dependencies: Supabase’s compose file might have Kong depend on other services (like PostgREST, Auth, etc.) with a healthcheck condition. Ensure those remain intact. We aren’t altering Kong’s internal config here, just how it’s accessed externally.
With those changes, your
docker-compose.ymlKong service might look like this (abridged example):Notice we did not change Kong’s internal ports (still 8000/8443) or disable any service. We simply added OrbStack-specific labels. OrbStack will see these labels and handle the domain and routing automatically.
Updating Environment Variables for the New Domain
Next, we need to update Supabase’s configuration so that it knows about our custom domain. Supabase’s Docker setup uses a
.envfile to populate service settings. Key variables to update:SUPABASE_PUBLIC_URL: This should be the URL that end-users (or the Supabase Studio) will use to reach your Supabase API. By default, in
.env.exampleit’shttp://localhost:8000github: supabase/.env.example. Change this tohttps://api.your-app.local. This ensures that when Supabase services construct URLs (for example, the Studio linking to APIs, or GoTrue constructing return URLs), they use theapi.your-app.localaddress over HTTPS.API_EXTERNAL_URL: This is used by the GoTrue (auth) service to know its external endpoint. In the example env it’s
http://localhost:8000github: supabase/.env.example. Change this tohttps://api.your-app.local. This is crucial for things like email confirmation links – by default, GoTrue will use this value as the base for links (unless overridden by headers). Setting it to our secure domain ensures email verification links, OAuth redirects, etc., point tohttps://api.your-app.local.SITE_URL: This should be the URL of your frontend or where users are redirected after auth. By default it might be
http://localhost:3000for a local dev frontend github: supabase/.env.example. You can keep this as is if your web app runs on localhost:3000, but ensure that domain is listed in GoTrue’s allowed redirects.After changes, your
.env(or environment section in the compose) should include for example:SUPABASE_PUBLIC_URL=https://api.your-app.local API_EXTERNAL_URL=https://api.your-app.local SITE_URL=http://localhost:3000 # or your app’s URL, ensure it's reachableIf you use the Supabase Studio (the web dashboard included in the stack), it will derive its API URL from
SUPABASE_PUBLIC_URL. Supabase Studio runs as thestudioservice (port 3000 in the stack) and proxies requests through Kong. By having the correct public URL set, Studio will callhttps://api.your-app.localfor all API calls instead of localhost.Finally, double-check any other service-specific URLs/ports in the
.env. For example,POSTGRES_HOSTcan remaindb(container name), and internal ports remain unchanged. The critical ones to align with our domain were the public/base URLs.How Kong and OrbStack Handle HTTPS and Routing
With the above configuration, here’s what happens when you access Supabase:
DNS and Domain Resolution: When you open
https://api.your-app.localin a browser on your Mac, OrbStack’s resolver directsapi.your-app.localto the OrbStack proxy. OrbStack’s proxy sees a request forapi.your-app.localon port 443 and finds the container with the matching domain label. It will present a TLS certificate forapi.your-app.localthat it generated and signed with its local CA (which is already trusted on your Mac) OrbStack HTTPS docs. Thus, the browser gets a valid HTTPS connection (the certificate will chain to “OrbStack Local CA”). You don’t need to manually create or trust certificates — OrbStack did this when you first used an.orb.localdomain and asked you to trust its CA OrbStack HTTPS docs.Proxy to Kong: OrbStack’s proxy terminates the TLS and forwards the HTTP request to the Kong container’s port 8000 (because of
dev.orbstack.http-port=8000). Kong receives an HTTP request on 8000 with the Host headerapi.your-app.local. (OrbStack preserves the Host header, so Kong “sees” the original domain in the request.)Kong’s routing: Kong is running with the Supabase declarative config (
kong.yml). In that config, Kong has routes set up with path prefixes for each service. For example, requests to/rest/v1/...are forwarded to the PostgREST service on therestcontainer (usually at http://rest:3000/) github: supabase kong config. Requests to/auth/v1/...are forwarded to the GoTrue auth service (http://auth:9999/) github: supabase kong config. There are similar routes for/storage/v1,/realtime/v1, etc., and a catch-all for Studio at the root path. All these routes are defined under Kong’s single domain (it doesn’t require the request to have any specific hostname, just the path). This means Kong doesn’t care that the Host isapi.your-app.local– it will match the path and proxy accordingly.CORS handling: By default, Supabase enables Kong’s CORS plugin on all the API routes github: supabase kong config github: supabase kong config. The
corsplugin is applied (with default settings allowing any origin) to/rest/v1/,/auth/v1/, etc. This means Kong will automatically addAccess-Control-Allow-Origin: *(or mirror the request origin) and other CORS headers in responses github: supabase kong config. In practice, this prevents CORS issues when your frontend (e.g. running onlocalhost:3000) callshttps://api.your-app.local.Response: Kong proxies the response back through OrbStack’s proxy, which then encrypts it to the client. From the perspective of your browser or client, it made an HTTPS request to
api.your-app.localand got a valid response. Everything in between (OrbStack proxy to Kong, Kong to upstream service) is invisible to the client.At this point, you should be able to use Supabase as if it were a hosted service at
api.your-app.local. For example:https://api.your-app.local/rest/v1/(with the appropriate headers/token) will reach your database via PostgREST./auth/v1/) will be served by GoTrue. For instance, the Magic Link emails will contain URLs pointing toapi.your-app.local(since we setAPI_EXTERNAL_URL), which will route back in through Kong.wss://api.your-app.local/realtime/v1. OrbStack’s proxy also supports secure WebSockets because it’s just TLS passthrough to Kong’s HTTP (Kong will handle the upgrade to WS).Note on Basic Auth: Supabase’s Kong config also enables the
basic-authplugin for the/route (Studio) and secures some endpoints with API keys (for service vs anon roles) github: supabase kong config. When you visithttps://api.your-app.localin a browser, Kong will likely prompt for the Studio login (using the credentials from your env). This confirms that the root path is being served by Kong/Studio over our custom domain.Enabling LAN Access (Access from Other Devices)
The above setup works great on the local machine (because OrbStack automatically manages DNS resolution and TLS trust on the host). If you need to access the Supabase stack from another device on your LAN (say a phone or another computer for testing), additional steps are needed:
DNS resolution on the other device: The device needs to resolve
api.your-app.localto your Docker/OrbStack host (your Mac)’s IP address. OrbStack’s internal DNS for.orb.localis only configured on the Mac itself by default. On another device,api.your-app.localwon’t resolve unless you configure it. The simplest way is to add an entry to the device’s hosts file pointingapi.your-app.localto your Mac’s LAN IP (e.g.,192.168.1.100 api.your-app.local).Trusting OrbStack’s CA on the device: OrbStack’s certificate authority is by default trusted on your Mac (it’s added to Keychain on first use) OrbStack HTTPS docs. Other devices won’t know about it. You’ll need to export OrbStack’s root CA certificate and install it on the device so that the certificate served for
api.your-app.localis trusted.Using the domain vs. direct IP: It’s preferable to use the
api.your-app.localdomain on the other device (after setting up DNS and trusting the CA) rather than a raw IP, to avoid certificate mismatches and bypassing OrbStack’s proxy.Testing on LAN: After adding a hosts entry and installing the CA, try loading
https://api.your-app.localon the other device. It should connect to your Mac (make sure your Mac’s firewall allows the connection). OrbStack’s proxy listens on all interfaces for the.orb.localdomains, so it should accept connections from the LAN as well.(Optional) Having Kong Terminate HTTPS with OrbStack Certificates
In the default approach, OrbStack’s proxy handles all HTTPS while Kong receives plain HTTP. This is usually sufficient for local development. However, if you want Kong to serve HTTPS directly using custom certificates, you can mount your own cert and key into the container and set
KONG_SSL_CERTandKONG_SSL_CERT_KEYStack Overflow. For example:Then instruct OrbStack to forward TLS traffic to Kong’s 8443 port by using:
Note that obtaining a certificate signed by OrbStack’s CA isn’t supported—you would need to use your own or a tool like mkcert.
Final Verification
After configuring everything:
docker compose up -d --force-recreate). OrbStack will register the custom domain.https://api.your-app.localin a browser, OrbStack may prompt you to install its CA (if not already done) OrbStack HTTPS docs.https://api.your-app.localto see the Supabase Studio login page and verify that API endpoints (e.g./rest/v1/and/auth/v1/) are working.Everything we’ve done maintains an architecture similar to production:
api.your-app.local)localhostURLs in the client configurationIn practice, you can now develop against your local Supabase by pointing your application to
https://api.your-app.localand have it behave nearly identically to a deployed instance.Conclusion
By leveraging OrbStack’s wildcard domain and automatic HTTPS features, we set up a local Supabase environment that mirrors production behavior. The key steps were adding OrbStack domain labels in Docker Compose and updating Supabase’s environment variables to use
https://api.your-app.localas the base URL. OrbStack’s reverse proxy and CA handle routing and certificate management so that Kong and the other containers work as if they’re in a real hosted environment. With Kong’s default configuration (using path-based routing) and the built-in CORS plugin github: supabase kong config, your frontend can call the API without issues.References:
Beta Was this translation helpful? Give feedback.
All reactions