Skip to content

GitHub App

Nexul talks to GitHub through a single GitHub App. It signs people in, connects your workspace to GitHub, lets runners clone private repositories to build them, and — while your instance’s own repository is private — downloads runner binaries from its releases. You create this App once, then paste its details into the setup wizard.

It has to be a GitHub App, not an OAuth App: only a GitHub App has fine-grained repository permissions and installations, and an OAuth App can’t be converted into one later.

Go to GitHub → Settings → Developer settings → GitHub Apps → New GitHub App.

Field Value
GitHub App name Anything — the URL slug it produces is what Nexul asks for.
Homepage URL Your instance URL, e.g. https://deploy.example.com.
Callback URLs <instance>/auth/callback (sign-in) and <instance>/auth/connectors/github/callback (connector). For local dev, add the same two paths under http://localhost:5173 and http://localhost.
Expire user authorization tokens On — Nexul refreshes tokens itself.
Request user authorization (OAuth) during installation On.
Webhook Leave inactive. Nexul registers per-repository webhooks itself.

Set these repository permissions:

Permission Level
Metadata Read (mandatory on every GitHub App)
Contents Read
Pull requests Read and write
Webhooks Read and write

Contents: Read matters more than it looks — without it, a runner cloning a private repository fails with “Write access to repository not granted”. Grant no organization or account permissions, and no Actions permissions.

Generate a client secret on the App’s page and save it. GitHub only shows it to you once.

On the App’s page, click Install App, choose your account, and pick All repositories. Every repository you want to deploy needs the App installed on it — including your Nexul instance’s own repository, while it’s private, since the runner install command downloads release binaries through the connector’s token.

  • First boot (/setup) — instance URL, OAuth client ID, client secret, App slug. This page shows the exact callback URL and verifies the slug against GitHub before letting you continue. See Setup wizard.
  • Owner wizard’s “Connect your tools” step, or Settings → Connectors → GitHub → Connect — the OAuth consent round trip. If you already authorized the App while installing it, there’s no consent screen to click through.
  • Rotating credentials — Settings’ GitHub App card takes a new client ID and secret at any time. Nothing lives in environment variables.

Raising or adding a permission on the App doesn’t apply to installations that already exist. GitHub sends the installation owner a request instead: Settings → Applications → Installed GitHub Apps → Configure → Review request → accept. Until you accept it, the token keeps its old permissions, and anything that needed the new one — a clone, a webhook call — keeps failing.

  • Sign-in only uses the user’s own token, and only to read their profile.
  • The connector token — the one Settings → Connectors stores when you connect — is what the server uses for repositories, pull requests, webhooks, and release downloads, and what it hands a runner for a build job. Reconnecting in Settings issues a fresh token; do that if a token ever ends up somewhere it shouldn’t.

Once the App is installed and connected, add a runner and deploy your first stack.