Axiom StudioAXIOMSTUDIO
All docs

GitHub Enterprise (ghe.com) — Setup Guide

Audience: anyone connecting a GitHub Enterprise Cloud data-residency tenant (*.ghe.com) to VibeFlow. This is the hands-on, step-by-step walkthrough, including the gotchas that actually bite. For the architecture and ops runbook, see the companion github-enterprise.md.


What you're setting up

GitHub Enterprise Cloud with data residency puts a customer on an isolated tenant with its own subdomain — e.g. https://axiomstudio-vibeflow.ghe.com, API at https://api.axiomstudio-vibeflow.ghe.com. A github.com GitHub App cannot serve that tenant (different, isolated host), so the customer registers their own GitHub App on their tenant and pastes its credentials into VibeFlow. One configuration per VibeFlow organization; all projects in that org share it.

Login stays SAML — there is no GitHub OAuth anywhere in this flow.

Once connected, the App powers: PR creation, PR comments, QA/Security check runs, issue sync, commit links, and cloud-runner git access — all against the tenant.


Prerequisites

#Requirement
1A GitHub Enterprise Cloud data-residency tenant (e.g. axiomstudio-vibeflow.ghe.com) and enterprise-owner access to it.
2An organization inside that enterprise that you own, with a test repo. Apps install on organizations — you cannot install on an EMU user account.
3A VibeFlow deployment reachable from the tenant over HTTPS (e.g. https://cloud-uat.axiomstudio.ai). The tenant must be able to POST webhooks to it.
4Access to the VibeFlow Integrations tab as a workspace-org admin (see Access & the gate).
5For cloud-runner clone/push: the cortex/nimbus backend that VibeFlow talks to must include the host-aware git-credentials fix (cortex develop ≥ commit a0dcd516). Control-plane features — PRs, checks, Test Connection — do not need this.

The flow at a glance

1. Create the GitHub App on the tenant   ──►  get App ID + private key (.pem)
2. Save the VibeFlow card (host, App ID, .pem, webhook secret)
                                           ──►  card shows the per-org Webhook URL
3. Put that Webhook URL + secret back into the GitHub App
4. Test Connection in the card             ──►  green + Install link appears
5. Install the App on an org + repos       ──►  webhook fires → "Installation detected"
6. Link a repo to a project → create a runner → clone/push

There is a deliberate two-pass on the webhook (steps 1→3): you need the App ID to save the card, and you need the card's saved config to learn the per-org Webhook URL. GitHub Apps are editable, so you finish the webhook fields in step 3.


Part 1 — Register the GitHub App on your tenant

On https://<sub>.ghe.comSettings → Developer settings → GitHub Apps → New GitHub App.

Basic information

FieldValue
GitHub App nameanything, e.g. axiomstudio-enterprise-app
Homepage URLyour VibeFlow base URL, e.g. https://cloud-uat.axiomstudio.ai

Identifying and authorizing users — turn these OFF

Login is SAML, so the App never does GitHub OAuth:

  • Callback URL — leave empty (if the field insists on a value, it's harmless since the next box is off).
  • Request user authorization (OAuth) during installationunchecked.
  • Enable Device Flowunchecked.
  • Expire user authorization tokens — irrelevant (leave default).

Post installation

  • Setup URL — leave empty. Install detection is webhook-driven; pointing it at a VibeFlow endpoint just lands the installer on a JSON page.
  • Redirect on update — off.

Webhook

  • Active — checked.
  • Webhook URL — for now put a placeholder (you'll replace it in Part 3 with the per-org URL). ⚠️ This is the field people get wrong — see The #1 gotcha.
  • Secret — you'll set this in Part 3 to match the card's secret.
  • SSL verificationEnabled.

Permissions (Repository permissions)

Set exactly these; nothing else:

PermissionAccess
ContentsRead and write
Pull requestsRead and write
ChecksRead and write
IssuesRead and write
MetadataRead-only (auto-selected)

No Organization or Account permissions are required.

Subscribe to events

Check: Pull request, Issues, Push. (installation, installation_repositories, and meta are delivered automatically — you don't tick them.)

Where can this GitHub App be installed?

  • This enterprise — recommended, so you can install it on organizations in the enterprise.
  • Only on this account restricts installation to the owning account only.

Create the app. Then:

  • Note the App ID — the numeric id on the app's General/About page (e.g. 17921). ⚠️ Use the App ID, not the Client ID.
  • Generate a private key → a .pem downloads (GitHub shows it once — keep it safe; it's the app's signing key).

Part 2 — Configure the VibeFlow card

VibeFlow → project → Integrations tab → GitHub Enterprise (a separate card, below the regular GitHub one).

FieldValue
Enterprise hostthe bare subdomain, e.g. axiomstudio-vibeflow (it derives https://api.axiomstudio-vibeflow.ghe.com; a full URL works too)
App IDthe numeric App ID from Part 1
Display namefree text, e.g. Axiom Studio Enterprise
Private keyupload the .pem (or paste its contents)
Webhook secretclick Generate, then Copy it now — it's write-only and shows •••• configured after saving
Enabledcheck it

Click Save configuration.

After saving, the "APP REGISTRATION ON YOUR TENANT" section appears with the per-org Webhook URL (and, after Test Connection, the Install link). Copy that Webhook URL.


Part 3 — Finish the webhook on the GitHub App

Back in the GitHub App settings:

  1. Webhook URL → paste the exact per-org URL from the card. It looks like:
    https://cloud-uat.axiomstudio.ai/rest/v1/vibeflow/github/webhook/<ORG_ID>
    
    where <ORG_ID> is your VibeFlow organization's id.
  2. Secret → paste the same secret you generated in the card.
  3. Save.

GitHub sends a fresh ping on every webhook change — see verification.


Part 4 — Test Connection

In the card, click Test Connection. It builds an App JWT from your stored credentials and calls GET https://api.<sub>.ghe.com/app:

  • Green → "Connection OK — app "<name>" with N installations". This proves your App ID + private key + host are all correct, and stores the app slug. The Install link now appears.
  • Errors are classified: bad_credentials (App ID / key wrong), app_not_found / unreachable_host (host wrong).

0 installations at this point is expected — you haven't installed it yet.


Part 5 — Install the App & verify it end to end

  1. Click the Install link in the card (https://<sub>.ghe.com/apps/<app-slug>/installations/new), or install from the org → Settings → GitHub Apps side.
  2. Choose an organization in the enterprise and select the repos VibeFlow may touch. (If the account list is empty, see troubleshooting.)
  3. Verify in GitHub App → Advanced → Recent Deliveries:
    • the installation event returns 202
    • the card flips from 0 installations to "Installation detected".
  4. In VibeFlow, link that repo to a project (project → Settings).
  5. Create a cloud runner on the project and confirm it clones + pushes. (Runner clone/push needs cortex ≥ a0dcd516.)

The #1 gotcha: the Webhook URL needs your org id

The regular github.com webhook route is …/rest/v1/vibeflow/github/webhook. The enterprise route is per-organization: …/rest/v1/vibeflow/github/webhook/<ORG_ID>.

If you leave off the /<ORG_ID>, the delivery hits VibeFlow's github.com handler, which verifies against the deployment's github.com secret — not your enterprise secret — and fails. The response code tells you exactly where it landed:

ResponseMeaningFix
400 {"error":"Invalid signature"}Hit the github.com route — URL is missing /<ORG_ID>Set the Webhook URL to the per-org URL from the card
401 {"error":"Invalid signature"}Reached the enterprise route, but the secret doesn't matchMake the GitHub App's webhook secret identical to the card's
404Unknown/disabled org id in the URLUse the exact URL the card generated; ensure the config is Enabled
202 {"status":"ok"}✅ Verified and processed

The card only reveals the per-org URL after you save, which is why the setup is a two-pass on the webhook. When you change the webhook, GitHub re-sends a ping; look at the newest delivery (or hit Redeliver) — a stale earlier delivery keeps its old snapshot in the payload body.


Troubleshooting

Empty "Install" list

On a data-residency (EMU) enterprise, apps install on organizations, and the install page lists only orgs where you are an owner.

  • Set the App's "Where can this GitHub App be installed?" to This enterprise.
  • Make sure you own an organization in the enterprise (create one under Enterprise → Organizations → New organization, with a test repo).
  • Reload the install page, or install from org → Settings → GitHub Apps.

Test Connection fails

  • bad_credentials → the App ID and/or private key don't match. Re-check the numeric App ID and re-upload the .pem.
  • app_not_found / unreachable_host → the host is wrong. Use the bare subdomain; the API base must resolve to api.<sub>.ghe.com.

Card doesn't appear at all (Integrations tab)

The card is gated to workspace-org admins. See Access & the gate.

Runner clones an empty workspace / push fails

  • Empty clone → the cortex/nimbus build is older than a0dcd516 (host-aware credentials). Deploy the cortex fix.
  • Push fails after ~1 hour → the token TTL (see known limitations).

Access & the gate

The GitHub Enterprise card and its /rest/v1/admin/github-enterprise endpoints are normally gated to organization admins of a workspace org (an org whose name is a bare domain, i.e. contains no @). This mirrors the SAML SSO gate.

  • If the card isn't visible, check …/rest/v1/user/is-admin and …/rest/v1/user/is-workspace-org — both must be true.
  • In some test environments this gate is temporarily relaxed to any authenticated user; that relaxation is tracked and must be restored before production.

Note: even under the relaxed gate, org_id always comes from the session — tenant isolation is never relaxed.


Known limitations

  • Runner push window = 1 hour. Cloud-runner git credentials are GitHub App installation tokens (GitHub-capped at 1 hour), injected once at runner start. Clone at start and control-plane PR/checks are unaffected, but a push more than ~1 hour into a session fails until the runner restarts. A call-home token-refresh is the planned follow-up.
  • User PATs and MCP PAT tooling stay github.com-only.
  • Data residency is a data-flow question: the VibeFlow control plane pulls PR diffs and repo content out of region for PR creation, checks, and diff display. Surface this to the customer's security review before go-live — it needs an owner.

Quick reference — what goes where

ValueGitHub App pageVibeFlow card
Tenant host(the tenant you're on)Enterprise host = bare subdomain
App ID (numeric)General/About pageApp ID
Private key (.pem)Generate → downloadsPrivate key (upload)
Webhook secretWebhook → SecretWebhook secret (Generate → copy) — must match
Webhook URLWebhook → URL (…/webhook/<ORG_ID>)shown after Save, in "App registration"
App slug(auto, from name)filled by Test Connection
PermissionsContents/PRs/Checks/Issues RW, Metadata R
EventsPull request, Issues, Push

Companion docs: github-enterprise.md (architecture & ops runbook) and the Somecompany onboarding checklist.