Skip to main content

Supabase's June 2026 Changelog Breaks Self-Hosted Auth — Here's What Actually Fails

8 min readDora NodaDora Noda
Share
On this page

Two lines in a changelog, four days apart. One is a real breaking change with a documented failure mode — a GitHub issue where a self-hosted OIDC discovery endpoint started returning an empty issuer. The other, despite reading like it applies to every Supabase deployment everywhere, doesn't touch self-hosted Postgres at all.

If you run Supabase from docker-compose.yml or a Cluster API–scheduled fleet, here's the actual breakage matrix: API_EXTERNAL_URL breaks OAuth and SAML, but only if you're caught mid-upgrade with mismatched config; log_connections changes nothing on your box, no matter what you do. Below is exactly which config lines to check, when each change bites, and why "self-hosted" means your team inherits the vendor's changelog as an operational to-do list — not just its Dockerfile.

What Actually Changed

On July 7, 2026, supabase/supabase's docker/CHANGELOG.md shipped v0.7.0 with two flagged entries:

⚠️ Changed the default API_EXTERNAL_URL in .env.example to contain /auth/v1

⚠️ Changed GOTRUE_JWT_ISSUER to match the new default API_EXTERNAL_URL (requires docker-compose.yml update)

Here's the before/after, pulled directly from the current docker/.env.example, docker-compose.yml, and volumes/api/kong.yml in the supabase/supabase repo:

Config valueBefore v0.7.0After v0.7.0
API_EXTERNAL_URL defaulthttp://localhost:8000http://localhost:8000/auth/v1
GOTRUE_JWT_ISSUER${API_EXTERNAL_URL} (resolves to a bare host)${API_EXTERNAL_URL} (now resolves to .../auth/v1)
OAuth redirect placeholder${API_EXTERNAL_URL}/auth/v1/callback${API_EXTERNAL_URL}/callback
SAML SSO routes/sso/saml/acs, /sso/saml/metadata/auth/v1/sso/saml/acs, /auth/v1/sso/saml/metadata

The mechanism: GoTrue (Supabase's auth service) builds OAuth callback URLs and its own JWT issuer string by concatenating API_EXTERNAL_URL with a suffix. Kong, the API gateway in front of it, has always routed /auth/v1/* to the auth container — that part never moved. What changed is which half of the /auth/v1/callback path lives in the base URL versus the suffix. Push /auth/v1 into the base URL, and the suffix has to drop it, or you get /auth/v1/auth/v1/callback and a 404.

When It Actually Breaks — and When It Doesn't

This is a no-op for a fresh install. If you clone the repo today and copy .env.example to .env without editing API_EXTERNAL_URL, everything lines up: the new default already has /auth/v1 in it, and the new docker-compose.yml callback placeholder already expects that. Nothing to do.

The breakage shows up in exactly one scenario: a mixed-state upgrade. You've been running self-hosted Supabase for a while, you've overridden API_EXTERNAL_URL in your own .env to your real domain (say, https://db.example.com, set under the old convention with no /auth/v1 suffix), and you git pull a newer docker/ directory that carries the new docker-compose.yml — but you don't touch your existing .env. Now:

  • GOTRUE_JWT_ISSUER resolves to https://db.example.com instead of https://db.example.com/auth/v1.
  • The OAuth callback GoTrue constructs and registers with a custom provider (Google, GitHub, Azure) resolves to https://db.example.com/callback — a path Kong has never routed — instead of https://db.example.com/auth/v1/callback.
  • If you use SAML SSO, your identity provider is still pointed at the old /sso/saml/acs and /sso/saml/metadata paths, which the new Kong config no longer serves at that location.

This isn't hypothetical. supabase/auth issue #2487 documents a self-hosted deployment where the .well-known/openid-configuration discovery endpoint started returning an empty issuer field and relative endpoint paths ("/oauth/authorize" instead of a full URL) instead of the expected https://<domain>/auth/v1 issuer — verified directly against the auth container on port 9999, ruling out Kong as the cause. The report was assigned and linked to a fix PR (#46020), confirming it as a real issuer-construction bug rather than a one-off misconfiguration. Any client validating the JWT issuer claim against a URL — mobile app deep links, a second service checking iss — breaks the moment API_EXTERNAL_URL and the compose file's expectations diverge.

The fix is one line: update API_EXTERNAL_URL in your .env to include the /auth/v1 suffix, redeploy, and — only if you use SAML — update your IdP's registered ACS and metadata URLs to the new /auth/v1/sso/saml/* paths. If you don't use SAML and you pull .env.example and docker-compose.yml together instead of patching one and not the other, there is nothing to fix.

The log_connections Claim Doesn't Hold for Self-Hosted

The second changelog entry, four days later, reads like the same category of change: Supabase flipped the Postgres log_connections setting from on to off by default, for new projects across every tier, and migrated existing Free and Pro projects to the new default starting July 9, 2026 — cutting log volume and matching the default RDS and Cloud SQL already ship. Re-enabling it is one toggle in the dashboard under Database → Settings, or a call to the Management API's postgres-config route.

That entire mechanism doesn't exist for a self-hosted deployment, and here's why: there's no Management API touching your Postgres instance, because there's no managed Postgres instance. Two facts settle it.

First, docker-compose.yml's db service only passes one Postgres flag on the command line — log_min_messages=fatal, added specifically to keep Realtime's polling queries out of the logs. It does not set log_connections at all.

Second, the supabase/postgres image (the base Postgres distribution self-hosted stacks actually run) ships a config template with log_connections commented out — #log_connections = off — deferring to Postgres's own compiled-in default, which is off. The on value referenced in Supabase's changelog is a runtime override (postgres -c log_connections=on) applied specifically by Supabase's own cloud provisioning layer when it spins up a managed database. Self-hosted Docker deployments were never given that override, so they were never "on" in the first place — there's nothing for this changelog entry to flip.

Net effect for a self-hosted docker-compose or Cluster API–scheduled stack: this change is a complete no-op. Nothing breaks, nothing changes, and there's no dashboard toggle to go check, because the toggle it refers to belongs to Supabase's hosted control plane. If connection-level audit logging is something your compliance posture actually needs, it was never Supabase's default to lose — set it yourself, directly in your own Postgres config or as a command-line override in docker-compose.yml:

yaml
command:
  [
    "postgres",
    "-c",
    "config_file=/etc/postgresql/postgresql.conf",
    "-c",
    "log_min_messages=fatal",
    "-c",
    "log_connections=on"
  ]

What This Means on a Cluster API–Scheduled Fleet

Running Supabase behind Cluster API instead of raw docker-compose changes where you have to make the fix, not whether you have to. The community-maintained supabase-community/supabase-kubernetes Helm chart — explicitly not officially supported by Supabase, with issues routed to the community repo instead — wraps the same auth, kong, and postgres containers behind Helm values instead of a .env file. docker/CHANGELOG.md's migration guidance doesn't propagate to that chart automatically; nobody is watching upstream on your behalf.

Before pulling a chart update on a CAPI-managed fleet, check three things in your values.yaml (or whatever CRD wraps it):

  1. Whatever value maps to API_EXTERNAL_URL — confirm it already carries /auth/v1, the same way you'd check .env on docker-compose.
  2. GOTRUE_JWT_ISSUER — should derive from the same value, not be hardcoded separately from an older chart version.
  3. Any OAuth provider redirect URI values baked into your values file or secrets — confirm they match whichever placeholder convention the chart's current auth-service template uses, not the one from when you first deployed.

Skip the log_connections chase entirely — there's no equivalent Management API for a Helm-deployed Postgres pod to poll, and the base image behavior described above holds regardless of what's scheduling the container.

Self-Hosted Means Reading the Changelog Yourself

Neither of these two lines is really about Postgres logging or OAuth callbacks specifically. They're a small, dated case study in what "self-hosted" actually costs: nobody's dashboard silently migrates your config for you, and nobody's Management API quietly re-enables a setting you didn't ask to lose. You get the upstream project's changelog as a standing operational to-do list, and the two entries in it this month happened to need opposite responses — one needs a one-line .env fix before your next deploy, the other needs you to do precisely nothing and stop looking for a toggle that was never yours to flip.

That's a fair trade for owning the machine instead of renting someone else's abstraction of one, but it's a trade a team has to keep making consciously, release after release — not a one-time setup cost.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. If you're already self-hosting Supabase behind a Cluster API fleet, the same pattern applies to everything else you run there: read the upstream changelog, not the dashboard, because there isn't one. Star the repo on GitHub or deploy your first app today.


Sources

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex