Skip to content

fix(self-host): forward the configured scheme to workerd - #2251

Open
ntindle wants to merge 1 commit into
UsefulSoftwareCo:v2from
ntindle:fix/self-host-forwarded-proto
Open

ntindle wants to merge 1 commit into
UsefulSoftwareCo:v2from
ntindle:fix/self-host-forwarded-proto

Conversation

@ntindle

@ntindle ntindle commented Oct 10, 2026

Copy link
Copy Markdown

Fixes #2199.

Behind a proxy that ends TLS (Railway's edge, tailscale serve, or the HTTPS reverse proxy the self-host README recommends), every POST /api/dashboard/batch returns an empty 403. Pages that batch their reads then show "Unable to complete this request". This affects self-host from 2.0.0-beta.9 on.

Cause

The native host reaches workerd over plain HTTP. httputil.ReverseProxy removes the incoming X-Forwarded-* headers before Rewrite runs, so the product's HttpServerRequest.toURL builds http://<host>, and sameOrigin in packages/dashboard-start/src/implementation/batch-host.ts refuses the browser's Origin: https://<host>. SetXForwarded() would not help: it takes the scheme from the host's own plain-HTTP connection.

Fix

When BETTER_AUTH_URL is https://…, the host sets X-Forwarded-Proto: https on every request it forwards to workerd. The scheme comes from configuration, never from the client: a client-sent X-Forwarded-Proto is still dropped. The server-rendered pages that derive their origin the same way (document.ts, in-process.ts) get the right scheme too.

#2246 proposed the same approach and was closed by its author without comment. If you would rather compare the batch Origin with BETTER_AUTH_URL's origin in batch-host.ts, as the other hosted origin checks do, I'm happy to switch.

One behavior change: a server configured for https:// but opened over plain http:// now gets 403 on batches. Sign-in already fails in that setup.

Tested

  • gofmt -l, go vet and go test ./... in apps/hosted/self-host/native pass. The new TestProxyForwardsTheSchemeOfTheConfiguredOrigin fails without the change.
  • A 2.0.0-beta.13 image with this commit, beside the official 2.0.0-beta.13, both with BETTER_AUTH_URL=https://exec-test.example:4788: POST /api/dashboard/batch with the instance's own https:// Origin gets 403 from the official image and 400 from the patched one (origin accepted, empty batch refused). A foreign Origin, a missing Origin and a text/plain body still get 403. /health and unauthenticated /mcp are unchanged.
  • Running behind tailscale serve on our self-host since 2026-10-10: the same probe returns 400, and a foreign Origin 403.
none

🤖 Generated with Claude Code

Behind a proxy that ends TLS, such as Railway's edge, tailscale serve or the
HTTPS reverse proxy the self-host guide recommends, the native host reaches
workerd over plain HTTP. ReverseProxy's Rewrite removes the proxy's
X-Forwarded-Proto, so HttpServerRequest.toURL derives http://<host>. The
dashboard batch's same-origin check then refuses the browser's
Origin: https://<host> with an empty 403, and every page that batches its reads
shows "Unable to complete this request".

When BETTER_AUTH_URL is an https origin, the host now sets
X-Forwarded-Proto: https on every request it forwards to workerd. The scheme
comes from the configured origin, never from the client: Rewrite still removes
any X-Forwarded-Proto the client sent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant