Skip to content

feat: GitHub Enterprise Server (GHES) support #360

@raghavpillai

Description

@raghavpillai

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions