Log in
← Docs

Connect GitHub Actions

Point a kaniko build on GitHub Actions at this backend.

Five steps. Nothing is stored in your repository: the runner mints a short-lived token per build.

1. Install the app

Install the Firn GitHub App on the organisation that owns the repository.

It asks for Metadata: read-only on all repositories. Neither grants anything worth having; both are what makes the installation visible. GitHub only reports an installation to someone who can reach one of its repositories, so without them you would sign in owning nothing.

2. Sign in

Sign in with GitHub. Until something is shared with you, you land on the access page.

3. Ask for your organisation

The access page lists the organisations that installed the app. Request yours and wait for an admin to approve it.

The app is how people reach the dashboard. It grants a build nothing — that is the token in the next step.

4. Add the workflow

id-token: write is the whole credential. There is no secret to add. Already have a kaniko workflow? The + lines are all it needs.

# Which account these builds belong to comes from the token GitHub mints below,
# not from anything set here.
name: build

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      # The whole credential. Nothing is stored in the repository: the runner
      # mints a token per build and it expires in minutes.
      id-token: write
    env:
      KANIKO_TELEMETRY_ENDPOINT: "https://152.70.24.68.sslip.io/oidc/v1/traces"
      KANIKO_TELEMETRY_TOKEN_EXCHANGE_ENDPOINT: "https://152.70.24.68.sslip.io/ingest/token"
    steps:
      - uses: actions/checkout@v4

      # GitHub hands out a request URL rather than a token, so it is minted here.
      # It expires five minutes after minting, so keep this right before the build.
      - name: Get an identity token
        run: |
          set -o pipefail
          if TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
                       "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=kaniko-telemetry" | jq -er .value); then
            echo "::add-mask::$TOKEN"
            echo "KANIKO_TELEMETRY_ID_TOKEN=$TOKEN" >> "$GITHUB_ENV"
          else
            echo "no identity token - is id-token: write set? building without telemetry"
          fi

      - name: Build
        uses: docker://ghcr.io/osscontainertools/kaniko:v1.28.5-debug
        with:
          args: --destination=ghcr.io/${{ github.repository }}:${{ github.sha }}

5. Run it

The build appears under Builds a few seconds after the job finishes.

A refused exchange logs ingest token exchange refused and the build carries on without telemetry.

What the snippet does

The job asks GitHub for an identity token, kaniko trades it for an ingest token and sends that with its spans. The token lasts minutes and never leaves the job that asked for it.

Which account the build belongs to comes from that identity, not from anything the workflow sets.

If nothing arrives

Check the job log for exchange refused, and check the picker above matches the kaniko you run. Set KANIKO_TELEMETRY_ENDPOINT to https://152.70.24.68.sslip.io/oidc/v1/traces for that version — the endpoint differs between versions and the wrong one fails silently.