All GitHub URLs in the codebase are hardcoded to github.com. If you're running a GHES instance, nothing works — OAuth, App auth, API calls, git clone URLs, noreply emails, avatar URLs, PR creation links, all of it.
This replaces every hardcoded github.com / api.github.com reference with a configurable hostname. Set GITHUB_HOSTNAME=github.example.com and the rest follows: API base becomes https://github.example.com/api/v3, noreply domain becomes users.noreply.github.example.com, etc.
Scope
The change touches basically everything that talks to GitHub:
- control-plane: OAuth token exchange, GitHub App installation tokens, source control provider (PR creation, branch listing, repo access checks, git push URLs), participant avatar URLs
- github-bot: installation token generation, permission checks, reaction API calls
- modal-infra / daytona-infra: git clone/push URLs, noreply email fallback, image builder
ls-remote
- web: NextAuth GitHub provider config — split browser-side (user's browser hits GHES directly for OAuth) vs server-side (Worker routes through tunnel proxy for token exchange + API)
- terraform:
github_hostname, ghes_tunnel_url, and web_app_custom_url variables threaded through to workers
GHES in a private VPC
GHES instances are usually not on the public internet, which means Cloudflare Workers can't reach them directly. The GHES_TUNNEL_URL env var points to a reverse proxy (we used a Cloudflare Tunnel, but any tunnel that forwards to the GHES instance works). The web app sends the user's browser directly to GHES for OAuth authorize, then routes the server-side token exchange through the tunnel.
The daytona-infra package also includes a /ghes-proxy/{path} endpoint that forwards requests to GHES for the same reason — the infra API server runs inside the private network and can reach GHES directly.
Design
A single resolveGitHubUrls(hostname?) function derives all URL variants from the hostname. Every call site that previously hardcoded github.com or api.github.com now calls this (or receives the resolved URLs via config). Defaults to github.com when GITHUB_HOSTNAME is unset, so existing deployments are unaffected.
Depends on #359 (Daytona provider) for the daytona-infra pieces, but the control-plane/web/github-bot/modal-infra changes work independently.
All GitHub URLs in the codebase are hardcoded to github.com. If you're running a GHES instance, nothing works — OAuth, App auth, API calls, git clone URLs, noreply emails, avatar URLs, PR creation links, all of it.
This replaces every hardcoded
github.com/api.github.comreference with a configurable hostname. SetGITHUB_HOSTNAME=github.example.comand the rest follows: API base becomeshttps://github.example.com/api/v3, noreply domain becomesusers.noreply.github.example.com, etc.Scope
The change touches basically everything that talks to GitHub:
ls-remotegithub_hostname,ghes_tunnel_url, andweb_app_custom_urlvariables threaded through to workersGHES in a private VPC
GHES instances are usually not on the public internet, which means Cloudflare Workers can't reach them directly. The
GHES_TUNNEL_URLenv var points to a reverse proxy (we used a Cloudflare Tunnel, but any tunnel that forwards to the GHES instance works). The web app sends the user's browser directly to GHES for OAuth authorize, then routes the server-side token exchange through the tunnel.The
daytona-infrapackage also includes a/ghes-proxy/{path}endpoint that forwards requests to GHES for the same reason — the infra API server runs inside the private network and can reach GHES directly.Design
A single
resolveGitHubUrls(hostname?)function derives all URL variants from the hostname. Every call site that previously hardcodedgithub.comorapi.github.comnow calls this (or receives the resolved URLs via config). Defaults to github.com whenGITHUB_HOSTNAMEis unset, so existing deployments are unaffected.Depends on #359 (Daytona provider) for the
daytona-infrapieces, but the control-plane/web/github-bot/modal-infra changes work independently.