self-host →

CodeQL code scanning

Run GitHub CodeQL code scanning on RunsOn Fleet or Flex self-hosted runners, with default setup or advanced setup.

GitHub CodeQL code scanning can run on RunsOn runners instead of GitHub-hosted runners. GitHub offers two setups, and they select a runner differently:

SetupHow the runner is chosenFleetFlex
Default setupOne runner label in the repository or organization security settingsYesNo
Advanced setupThe runs-on: label of a CodeQL workflow you commitYesYes

Code scanning must be available on the repository: it is free for public repositories, and private or internal repositories need GitHub Code Security ↗.

Default setup on Fleet#

A Fleet runner scale set is registered with a single compound label, such as:

runs-on/fleet=codeql-x64/env=production

The fleet name and environment must match a fleet in your Fleet configuration. GitHub creates the CodeQL jobs, so there is no workflow YAML to change.

Select the fleet as the runner for default setup:

  1. Open the repository’s Settings → Advanced Security, or go directly to https://github.com/<ORG>/<REPO>/settings/security_analysis.
  2. In the CodeQL analysis row, select Set up → Default. If default setup is already enabled, open the row’s menu, select View CodeQL configuration, then Edit.
  3. Under Runner type, select Labeled runner.
  4. Enter the full Fleet label in Runner label.
  5. Enable or save the configuration.

You can also set the runner with the REST API:

gh api -X PATCH repos/<ORG>/<REPO>/code-scanning/default-setup \
-f state=configured \
-f runner_type=labeled \
-f runner_label='runs-on/fleet=codeql-x64/env=production'

To use the same runner across many repositories, set the label in an organization security configuration ↗.

GitHub only accepts the label if a runner with that label is available to the repository. A fleet’s scale set satisfies this check even when no runner is running, as long as the fleet’s runner group allows the repository. For a public repository, the runner group must also allow public repositories.

Sizing the fleet#

Default setup starts one job per detected language, in parallel, so a repository with four languages needs four runners at once. GitHub recommends ↗ at least 8 GB of RAM for codebases under 100,000 lines of code, and more for larger ones.

Default setup builds some compiled languages, such as Go, with autobuild, so the runner needs their toolchains. Use a -full image such as ubuntu24-full-x64, which is compatible with the GitHub-hosted runner image.

Default setup is not available on Flex#

Flex cannot be the runner for default setup. GitHub checks that a runner with the label is already registered when you save the setting, and Flex registers a just-in-time runner only when a job arrives. GitHub rejects the label with:

Code scanning default setup can only be enabled if a runner with the specified label is assigned to this repository.

Use advanced setup on Flex instead.

Advanced setup#

Advanced setup works on Flex and Fleet. Commit a CodeQL workflow and pick the runner with runs-on::

.github/workflows/codeql.yml
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: "30 4 * * 1"
permissions:
actions: read
contents: read
security-events: write
jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: runs-on=${{ github.run_id }}/runner=4cpu-linux-x64
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
- language: python
build-mode: none
- language: go
build-mode: autobuild
steps:
- uses: actions/checkout@v5
- uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
- uses: github/codeql-action/analyze@v4
with:
category: "/language:${{ matrix.language }}"

On Fleet, only the runs-on: line changes:

runs-on: runs-on/fleet=codeql-x64/env=production

GitHub does not process advanced setup results while default setup is enabled on the repository. The analyze step fails with:

CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled

Disable default setup before you add the workflow. New repositories can have default setup enabled on GitHub-hosted runners automatically, when the organization applies a security configuration such as GitHub recommended.

Troubleshooting#

  • Jobs stay queued. Check that the label matches the fleet exactly and that the fleet’s runner group allows the repository. Jobs that were queued before you changed runner group access are not picked up afterwards: cancel and re-run them.
  • No scan after changing the runner. Changing only the runner through the API does not start an analysis. Push to the default branch, or wait for the weekly scheduled scan.
  • Code scanning default setup can only be enabled if a runner with the specified label is assigned to this repository. The label has a typo, the runner group does not allow the repository, or the label targets Flex.