Skip to main content

Authenticate private repos with a GitHub App (removed)

Removed in chart 3.0.0

githubTokenInit was removed from the nullplatform-agent Helm chart in version 3.0.0, released on September 1, 2026. A release that still sets it won't render: the chart aborts with an error pointing you at github.apps.

The init container minted one token at pod startup and never renewed it, and it supported a single installation ID. The agent now mints per-org installation tokens itself and renews them before they expire. See GitHub App auth for agent repos for the supported setup.

This page is kept for reference if you're still on chart 2.x. Everything below applies only to those versions.

When the agent reads scopes and actions from a private GitHub repository, chart 2.x can use a GitHub App to authenticate instead of embedding a personal access token in AGENT_REPO.

When to use this

The basic Helm install authenticates the agent repo via a token embedded in the URL:

AGENT_REPO="https://<git-token>@github.com/your-org/private-repo.git#main"

That works, but personal access tokens are long-lived, tied to a user account, and easy to leak via Helm history or kubectl describe pod. The GitHub App flow avoids both problems:

  • Short-lived credentials. Each pod start generates a fresh installation token (valid for one hour).
  • No personal account dependency. The App belongs to your GitHub organization, not to an individual.
  • Fine-grained permissions. You grant the App access only to the specific repos the agent needs.

How it works

When the chart is deployed with githubTokenInit.enabled=true, the agent pod runs an init container before the agent itself starts. The init container reads GitHub App credentials from a Kubernetes Secret, exchanges them for a short-lived token, and clones the repo into a shared volume that the agent container then reads.

🔒 The GitHub App private key never leaves the cluster. The init container generates the JWT locally and only the resulting installation token reaches GitHub.

Prerequisites

  • A Kubernetes cluster and Helm 3+ (same as the base Helm install).
  • A nullplatform API key with the agent and ops roles. See Authenticate the agent.
  • A GitHub App installed on the organization that owns the agent repo, with read access to the repos you want to clone.

1. Set up the GitHub App

In your GitHub organization, create a new GitHub App with the following:

  • Repository permissions: Contents: Read-only, Metadata: Read-only.
  • A new private key (download the .pem file when GitHub shows it; you can't retrieve it later).

Then install the App on your organization and select the agent repo. After installation, note down:

  • The App ID (visible on the App's settings page).
  • The Installation ID (the numeric ID at the end of the URL after you install the App).
  • The contents of the private key .pem file.

2. Provide the credentials to the chart

The chart supports two patterns. Pick the one that fits your secrets workflow.

Option A: Chart-managed secret

The chart creates the Kubernetes Secret for you from values you pass via --set. This is the simplest option for development or single-team installs.

The private key value must be base64-encoded. Generate it from your .pem file:

export PRIVATE_KEY_B64=$(base64 -w 0 < path/to/private-key.pem)

Then pass all three credentials when you install the chart:

helm install nullplatform-agent nullplatform/nullplatform-agent \
--namespace nullplatform-tools --create-namespace \
--set githubTokenInit.enabled=true \
--set githubTokenInit.repositoryUrl=github.com/your-org/private-repo.git \
--set githubTokenInit.values.appId=<your_app_id> \
--set githubTokenInit.values.installationId=<your_installation_id> \
--set githubTokenInit.values.privateKey=$PRIVATE_KEY_B64 \
--set configuration.values.NP_API_KEY=$NP_API_KEY \
--set configuration.values.TAGS="$AGENT_TAGS"

The chart creates a Secret named github-app-secret and wires the init container to read from it.

Option B: Bring your own secret

For production or GitOps workflows, you typically manage Secrets through a tool like External Secrets Operator or sealed-secrets. In that case, pre-create the Secret yourself and point the chart at it.

Create a Secret with these three keys (default names: APP_ID, INSTALLATION_ID, PRIVATE_KEY):

apiVersion: v1
kind: Secret
metadata:
name: github-app-secret
namespace: nullplatform-tools
type: Opaque
stringData:
APP_ID: "<your_app_id>"
INSTALLATION_ID: "<your_installation_id>"
PRIVATE_KEY: "<base64-encoded private key PEM>"

Then install the chart referencing the existing Secret:

helm install nullplatform-agent nullplatform/nullplatform-agent \
--namespace nullplatform-tools --create-namespace \
--set githubTokenInit.enabled=true \
--set githubTokenInit.repositoryUrl=github.com/your-org/private-repo.git \
--set githubTokenInit.secretName=github-app-secret \
--set configuration.values.NP_API_KEY=$NP_API_KEY \
--set configuration.values.TAGS="$AGENT_TAGS"

Override githubTokenInit.secretKeys.* if you use different key names in your Secret.

3. Verify the init container ran

Once the chart is installed, check the init container logs to confirm the clone succeeded:

kubectl logs -n nullplatform-tools <agent-pod-name> -c github-token-init

You should see the token request to GitHub and the repo clone output. If the agent pod is Running, the agent container is connected and the cloned repo is mounted at /root/.np/<repo-name>.

Then verify the agent appears in the platform UI under Platform settings > Agents.

Configuration reference

All values live under githubTokenInit in the chart values.

ValueDefaultWhat it does
enabledfalseAdds the init container that authenticates with GitHub and clones the repo
repositoryUrl""Repo URL to clone. Omit the https:// prefix (the init container prepends it with the token). Example: github.com/your-org/private-repo.git
secretNamegithub-app-secretName of the Kubernetes Secret holding the App credentials
secretKeys.appIdAPP_IDKey inside the Secret for the App ID
secretKeys.installationIdINSTALLATION_IDKey inside the Secret for the Installation ID
secretKeys.privateKeyPRIVATE_KEYKey inside the Secret for the base64-encoded private key
values.appId""App ID, when letting the chart create the Secret (Option A)
values.installationId""Installation ID, when letting the chart create the Secret (Option A)
values.privateKey""Base64-encoded PEM, when letting the chart create the Secret (Option A)
workingDir/root/.npShared volume mount path. Must match the agent's command executor base path
imagealpine:3.22.2Init container image. Must include apk

Refreshing the cloned repo

The init container runs only at pod startup. To pull new commits from the agent repo after the pod is running, restart the agent so the init container runs again with a fresh token:

kubectl rollout restart deployment/nullplatform-agent-<release-name> -n nullplatform-tools

With this init container flow, the agent container has no credentials of its own, so Refresh sources from the UI can't re-clone the repo. Treat pod restarts as the way to update the code the agent runs.

This is one of the reasons the init container was removed. On chart 3.0.0 and later, configure GitHub App auth for agent repos: the agent mints its own installation tokens, so Refresh sources works normally and no restart is needed.

Next step

Once the agent is installed and registered, create a notification channel so it can respond to platform events.

Create a notification channel →