For the complete documentation index, see llms.txt. This page is also available as Markdown.

GitHub

Set up GitHub for Lunar. Create the GitHub App the Hub authenticates as, review the permissions it holds, and serve several organizations from one Hub.

The Hub authenticates with a GitHub App installed on your organization. The App vends short-lived installation tokens, which Lunar uses to read repositories and post results, so no long-lived credential is stored anywhere.

You create the App; Lunar never creates one on your behalf. Either flow below produces the same App.

This page covers the GitHub side only. The install steps that consume it are in Prerequisites → Step 5 for self-hosted, or the Dedicated setup steps.

Permissions

The App ends up with these permissions however you create it: the setup tool sets them for you, and the manual flow has you set them by hand. This is the list to hand a security reviewer.

Permission
Access
Why

actions

read

Read workflow runs for CI data collection

checks

write

Post policy results as PR checks

contents

read

Fetch config and source for policy evaluation

metadata

read

Required by GitHub on every App

pull_requests

write

Post PR comments and statuses

repository_hooks

write

Auto-register per-repo webhooks

organization_hooks

write

Auto-register organization-level webhooks

Events: push, pull_request, workflow_run.

App creation

  1. Visit earthly.dev/lunar/github-app-setup.

  2. Follow the prompts. The tool uses GitHub's manifest flow to register the App with the permissions and events above.

  3. Download the PEM private key when prompted. GitHub shows it exactly once — if you click past this page, you'll have to generate a new key from the App settings later.

  4. Click Install App on GitHub and select the org. Choose All repositories unless you have a specific reason not to — Lunar's actual monitoring scope is configured in lunar-config.yml, so a narrower scope here just means coming back to Org Settings → GitHub Apps → Lunar → Repository access every time you add a new repo to Lunar.

The hosted tool proxies the manifest exchange to GitHub and returns the credentials to your browser; we never persist them.

Manual setup (alternative)

Create the App by hand when the hosted tool can't reach your environment — either of these:

  • GitHub Enterprise Server. The App has to be created on your own GHES instance.

  • Air-gapped, or earthly.dev is otherwise unreachable from the browser session you would run the tool in.

Create the App at GitHub's App creation page (or for an org: Org Settings → Developer settings → GitHub Apps → New GitHub App). For GHES, create it on your GHES instance instead. GitHub's registering-a-github-app docs walk through every form field if you want a reference.

Set the permissions and events above, then fill in the rest:

  • Homepage URL — any URL works (e.g. your internal Lunar URL, or https://earthly.dev/lunar).

  • Webhook — uncheck "Active." The Hub registers its own per-repo webhooks at runtime; the App-level webhook is unused. URL can be a placeholder (e.g. https://example.com/placeholder) — GitHub requires a value but nothing will ever hit it.

  • Webhook secret — leave blank. Since you unchecked "Active" above, GitHub won't deliver App-level events. The Hub's per-repo webhook signing secret is a separate thing — see prereqs Step 6.

  • Where can this app be installed? — "Only on this account."

Then, once the App exists:

  1. Generate a private key (App settings → "Private keys" → "Generate a private key"). Save the .pem file — GitHub does not show it again.

  2. Install the App on your organization (App settings → "Install App"). Choose All repositories unless you have a specific reason not to, for the same reason as above.

Whichever flow you used, you now hold four things: the owner, the App ID, the installation ID, and the PEM private key. Prereqs Step 5 lists where each one comes from. Confirm you have all four, and that the PEM is saved, before moving on.

Hub configuration (Dedicated)

Nothing to configure: Earthly runs the Hub and configures it for you. Continue at Dedicated → Deposit your credentials, where the PEM goes to your install rather than to Earthly. The self-hosted section below does not apply to you.

Hub configuration (self-hosted)

Those four values are what the Hub reads. Install Step 4 has the values block to paste; this is the reference behind it.

Setting
Chart value
Environment variable
Meaning

Owner

hub.github.app.owner

HUB_GITHUB_APP_OWNER

The org or user the App is installed on. Matching is case-insensitive and trimmed.

App ID

hub.github.app.id

HUB_GITHUB_APP_ID

Numeric. Quote it in YAML, or it renders as scientific notation.

Installation ID

hub.github.app.installId

HUB_GITHUB_APP_INSTALL_ID

Numeric, from the install URL.

Private key

mounted from lunar-github-app

HUB_GITHUB_APP_PRIVATE_KEY

The base64-encoded PEM.

Base URL

hub.github.baseUrl

HUB_GITHUB_BASE_URL

GHES only. Your instance's API endpoint.

Host

(none)

HUB_GITHUB_HOST

Defaults to github.com. On GHES set it to your instance hostname, so component names (<host>/org/repo) match what your manifests author.

All four App fields are required together. A partial configuration is rejected at startup.

Multiple organizations

When one Hub fronts several orgs that each install their own Lunar App, register one entry per owner in HUB_GITHUB_APPS instead of the single-App variables:

Each entry pins its own App credentials and installation; the Hub mints tokens scoped to the right org per request. Owner matching is case-insensitive and trimmed.

For the PEM files, the recommended pattern is one Kubernetes Secret with multiple keys, mounted as a single volume:

HUB_GITHUB_APPS is mutually exclusive with the single-App env vars (HUB_GITHUB_APP_OWNER / HUB_GITHUB_APP_ID / HUB_GITHUB_APP_PRIVATE_KEY / HUB_GITHUB_APP_INSTALL_ID). Use one mode or the other.

Next steps

Self-hosted installs carry these four values into Kubernetes secrets at prereqs Step 6, and into your chart values at install Step 4. On Dedicated you deposit the PEM into your install's secret drop instead.

For how GitHub and GitLab differ once Lunar is running, see Git Platforms.

Last updated