> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pullbase.io/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub App Integration

> Connect Pullbase to private Git repositories using a GitHub App.

Pullbase supports GitHub Apps to securely access private repositories without embedding personal access tokens.

## When to use a GitHub App

* Your configuration repository is private.
* You need auditable, revokable permissions scoped to specific repositories.
* You want Pullbase to fetch short-lived installation tokens on behalf of agents.

<Tip>
  You can start with public repositories (set `PULLBASE_GIT_ENABLED=false`). Add a GitHub App once you move configuration to a private repository.
</Tip>

## Create the GitHub App

<Steps>
  <Step title="Register the app">
    1. Visit [https://github.com/settings/apps/new](https://github.com/settings/apps/new) (or the equivalent GitHub Enterprise URL).
    2. Provide a descriptive **App name** (for example, `Pullbase Config App`).
    3. Set the **Homepage URL** to your Pullbase instance (`https://pullbase.example.com`).
    4. Set the **Callback URL** to `https://pullbase.example.com/api/v1/github-app/callback` (reserved for future enhancements).
    5. Leave the **Webhook** section disabled unless you plan to handle app-level webhooks separately.
  </Step>

  <Step title="Configure permissions">
    Grant only the permissions required:

    * Repository permissions → **Contents: Read-only**
    * Repository permissions → **Metadata: Read-only**
    * All other permissions: **No access**

    <Info>
      Pullbase only needs read access to fetch configuration files. Additional permissions are unnecessary and increase risk.
    </Info>
  </Step>

  <Step title="Install the app">
    Install the app on the organization/user that owns your configuration repository. Select the repositories Pullbase should access.
  </Step>

  <Step title="Capture credentials">
    After installation, record:

    * **App ID** — Found on the app's settings page under "About"
    * **App slug** — Lowercase name in the app's URL (e.g., `pullbase-config` from `github.com/apps/pullbase-config`)
    * **Installation ID** — Found in the URL after installing: `github.com/settings/installations/{installation_id}`
    * **Repository ID** — Query via GitHub API (see below)
    * **Private key** — Download the `.pem` file from "Private keys" section

    **Finding the Repository ID:**

    ```bash theme={null}
    # Using GitHub CLI
    gh api /repos/{owner}/{repo} --jq '.id'

    # Example
    gh api /repos/acme/infra-config --jq '.id'
    # Output: 964854370
    ```

    Or via curl:

    ```bash theme={null}
    curl -s https://api.github.com/repos/{owner}/{repo} | jq '.id'
    ```
  </Step>
</Steps>

## Configure Pullbase

### Environment variables

```env theme={null}
PULLBASE_GIT_ENABLED=true
PULLBASE_GITHUB_APP_ID=2113565
PULLBASE_GITHUB_APP_PRIVATE_KEY_PATH=/config/github-app.pem
PULLBASE_GITHUB_APP_API_BASE_URL=https://api.github.com
```

Mount the private key into the container at the configured path:

```yaml theme={null}
volumes:
  - ./config/github-app.pem:/config/github-app.pem:ro
```

<Warning>
  **Private key security:**

  * Set restrictive permissions: `chmod 600 github-app.pem`
  * Never commit the `.pem` file to Git
  * Use Docker secrets or a secrets manager in production
  * The `:ro` mount flag ensures the container cannot modify the key
</Warning>

**Using Docker secrets (recommended for production):**

```yaml theme={null}
services:
  central-server:
    image: pullbaseio/pullbase:latest
    environment:
      - PULLBASE_GITHUB_APP_PRIVATE_KEY_PATH=/run/secrets/github_app_key
    secrets:
      - github_app_key

secrets:
  github_app_key:
    file: ./config/github-app.pem
```

### GitHub Enterprise Server

For GitHub Enterprise Server (self-hosted), update the API base URL:

```env theme={null}
PULLBASE_GITHUB_APP_API_BASE_URL=https://github.mycompany.com/api/v3
```

The app registration and installation process is the same, but use your GitHub Enterprise URL instead of `github.com`.

### Environment-level configuration

When creating an environment (UI, CLI, or API) you provide GitHub App metadata:

```json theme={null}
{
  "name": "staging",
  "repo_url": "https://github.com/your-org/configs.git",
  "branch": "main",
  "deploy_path": "environments/staging/config.yaml",
  "installation_id": 89968159,
  "repository_id": 964854370,
  "app_slug": "pullbase-config"
}
```

## CLI validation

Use the bootstrap command to validate credentials locally before storing them on the server:

```bash theme={null}
pullbasectl github-app bootstrap \
  --app-id 2113565 \
  --private-key /config/github-app.pem \
  --installation-id 89968159 \
  --repository-id 964854370 \
  --app-slug pullbase-config
```

Add `--server-url`, `--admin-token`, and environment details to persist the configuration as part of environment creation.

## Agent flow

1. The environment stores GitHub App metadata (installation ID, repository ID, app slug).
2. An agent requests `GET /api/v1/agent/git-token` using its agent token.
3. Pullbase signs a JWT with the app's private key and calls GitHub's `/app/installations/{id}/access_tokens` endpoint.
4. Pullbase returns the short-lived installation token to the agent, which uses it for `git clone`.
5. Tokens expire in one hour; agents request fresh ones as needed.

## Troubleshooting

<AccordionGroup>
  <Accordion title="403 when cloning">
    * Verify the installation includes the repository. Check [https://github.com/settings/installations](https://github.com/settings/installations) for the app.
    * Confirm the app has `Contents: Read-only` permission.
  </Accordion>

  <Accordion title="Invalid private key">
    * Regenerate the `.pem` file from the GitHub App settings and update the mounted secret.
    * Ensure the file has restricted permissions (readable only by the Pullbase container).
  </Accordion>

  <Accordion title="Rate limiting">
    * GitHub Apps share a rate limit per installation. Reduce agent poll interval or enable webhooks to decrease token requests.
    * Check `Retry-After` headers in error responses.
  </Accordion>

  <Accordion title="Webhook signature mismatch">
    * Ensure the webhook secret in GitHub matches `PULLBASE_WEBHOOK_SECRET_KEY`.
  </Accordion>
</AccordionGroup>

<Tip>
  Use the GitHub CLI to inspect installation details:

  ```bash theme={null}
  gh api /app/installations --jq '.[].id'
  ```
</Tip>
