Infrastructure
Configure a GitHub App for a self-hosted Chalk metadata plane.
Chalk’s GitHub integration lets dashboard users install a GitHub App into their GitHub organization, connect Chalk projects to GitHub repositories, import repository contents into volumes, and open pull requests from a volume’s contents. A GitHub App powers the integration, and the metadata plane (the Chalk API server) holds its credentials.
In Chalk Cloud, Chalk operates this app for you. When you self-host the metadata plane, you register your own GitHub App and configure your API server with its credentials. This page walks metadata-plane administrators through that setup.
The API server authenticates to GitHub as a GitHub App:
No user-level OAuth is involved, and GitHub credentials are never sent to the browser: the dashboard talks only to the API server, which proxies all GitHub API access.
Create a new GitHub App at https://github.com/organizations/<your-org>/settings/apps/new
(or Settings → Developer settings → GitHub Apps → New GitHub App for a
personal account). Configure it as follows:
| Setting | Value |
|---|---|
| GitHub App name | A name for the app, such as Acme Chalk. GitHub derives the app’s URL slug from it, and you use the slug in Step 2. |
| Homepage URL | Your dashboard URL, such as https://chalk.acme.com |
| Setup URL | https://<your-dashboard-host>/github-redirect |
| Redirect on update | Enabled |
| Webhook | Disabled (the integration does not consume webhooks) |
| Where can this App be installed? | “Only on this account” works when all of your GitHub repositories are in one organization |
The Setup URL is required. After a user installs the app, GitHub redirects
their browser there with an installation_id and the state value from the
install link, and that page records the installation with the API server. If
the Setup URL is missing or points at the wrong host, the installation succeeds
on GitHub but never appears in Chalk.
Grant the following repository permissions:
| Permission | Access | Used for |
|---|---|---|
| Metadata | Read-only | Listing the repositories an installation can access |
| Contents | Read and write | Listing branches and downloading repository archives for volume imports (read), and pushing a branch for a pull request opened from a volume (write) |
| Pull requests | Read and write | Listing pull requests (read), and opening a pull request from a volume (write) |
| Workflows | Read and write (optional) | Opening a pull request from a volume when the pull request adds, changes, or deletes files under .github/workflows/. Without this permission, GitHub rejects those pull requests. |
A pull request opened from a volume makes the repository match the volume, so
it deletes repository files that are not in the volume. If the repository has
files under .github/workflows/ and the volume does not, the pull request
deletes them and needs the Workflows permission.
No account permissions or event subscriptions are needed.
After creating the app, scroll to Private keys and click Generate a
private key. GitHub downloads a .pem file.
Keep the key in the format GitHub provides: an RSA (PKCS#1) PEM beginning with
-----BEGIN RSA PRIVATE KEY-----. Do not convert it to PKCS#8
(-----BEGIN PRIVATE KEY-----); the API server only accepts the PKCS#1
format.
Note down from the app’s settings page:
Iv23...https://github.com/apps/<slug>Provide the app’s identity to the API server through environment variables:
| Environment variable | Required | Description |
|---|---|---|
CHALK_GITHUB_APP_ID | Yes | The numeric App ID |
CHALK_GITHUB_APP_SLUG | Yes | The app’s URL slug; the dashboard’s Install GitHub App button links to https://github.com/apps/<slug>/installations/new |
CHALK_GITHUB_APP_PRIVATE_KEY | Yes | The full PEM contents of the private key, including the BEGIN/END lines |
CHALK_GITHUB_APP_CLIENT_ID | No | The app’s client ID |
Set all three required variables together. If only some are present, the API server logs an error at startup and disables the integration for every team without its own explicit configuration.
If the API server runs on Kubernetes, add the variables to the secret that already backs the API server’s environment:
kubectl -n <api-server-namespace> patch secret <api-server-env-secret> \
--type merge \
-p "$(jq -n --rawfile key chalk-app.private-key.pem '{stringData: {
CHALK_GITHUB_APP_ID: "123456",
CHALK_GITHUB_APP_SLUG: "acme-chalk",
CHALK_GITHUB_APP_CLIENT_ID: "Iv23xxxxxxxxxxxxxxxx",
CHALK_GITHUB_APP_PRIVATE_KEY: $key
}}')"
Then restart the API server pods so they pick up the new environment. On a successful boot, the API server logs:
githubapp: default GitHub App enabled from environment
This environment-provided app acts as the default for every team on the
metadata plane. A team can override it with its own GitHub App through the
GitHubAppService/UpsertGitHubAppConfig RPC; an explicit per-team
configuration always takes precedence over the environment default.
/github-redirect on your dashboard, which
records the installation and links back to the settings page. The new
installation appears in the Installations list.Start every installation with Install GitHub App in the dashboard. The
link it opens carries a signed state value that ties the installation to
your Chalk team, and the link expires after 30 minutes. An installation
started from the app’s page on GitHub has no state, and the redirect page
shows Finish this installation from Chalk instead of recording it.
| Symptom | Likely cause |
|---|---|
failed_precondition: GitHub App not configured for this team | The CHALK_GITHUB_APP_* variables are not visible to the API server process (not set, set on the wrong deployment, or the pods were not restarted after the change), and the team has no explicit configuration. |
githubapp: ignoring invalid default GitHub App env configuration in API server logs | The variables are partially set, or CHALK_GITHUB_APP_ID is not a number. Set all of CHALK_GITHUB_APP_ID, CHALK_GITHUB_APP_SLUG, and CHALK_GITHUB_APP_PRIVATE_KEY. |
| The redirect page shows Finish this installation from Chalk | The installation was started from GitHub instead of from Chalk. Click Install GitHub App in Settings → Team → GitHub. The app is already installed on the GitHub account, so GitHub only asks you to confirm. |
the GitHub installation link is invalid or has expired; start the installation again from Chalk | The install link is more than 30 minutes old, or the private key was rotated after the link was created. Click Install GitHub App again. |
the GitHub account "<account>" is already connected to a different Chalk team; disconnect it there first | Each GitHub account can be connected to one Chalk team. Remove the installation from the other team’s Installations list, then install again. |
| Install completes on GitHub but never appears in the dashboard | The app’s Setup URL does not point at https://<your-dashboard-host>/github-redirect, or the installing user’s browser could not reach the dashboard afterwards. Fix the Setup URL, then click Install GitHub App again. Refresh from GitHub updates installations Chalk already has and does not add new ones. |
| Errors mentioning the private key when listing repositories or completing an installation | The key was converted to PKCS#8. Re-download the key from GitHub (it must begin with -----BEGIN RSA PRIVATE KEY-----), or rotate it and configure the new one. |
| Repository missing from the picker | The installation only grants access to selected repositories. Update the repository selection for the installation on GitHub, then click Refresh from GitHub. |
Opening a pull request from a volume fails on files under .github/workflows/ | The app does not have the Workflows permission. Add it in the app’s settings on GitHub, then accept the updated permissions for the installation. |
To rotate the app’s private key:
CHALK_GITHUB_APP_PRIVATE_KEY wherever the API server’s
environment is managed.Installation tokens are short-lived and re-minted on demand, so no other state needs to change. Install links created before the restart stop working; start any installation in progress again from the dashboard.