Use jobs.<job_id>.runs-on to define the machine a job runs on: a GitHub-hosted runner, a larger runner, or a self-hosted runner. Runners are targeted by labels, group membership, or both, and runs-on accepts a single string, a variable, an array of strings and variables, or a key:value pair using the group or labels keys. An array requires a runner matching every value — runs-on: [self-hosted, linux, x64, gpu] picks a self-hosted machine carrying all three labels — while jobs.<job_id>.strategy fans a job out across multiple machines. Quote expressions such as "${{ inputs.chosen-os }}"; simple strings like self-hosted need no quotes. On GitHub-hosted runners each job runs in a fresh instance of the runner image. Standard labels include ubuntu-latest (also ubuntu-24.04, ubuntu-22.04, and ubuntu-26.04), windows-latest (windows-2025, windows-2022), and macos-latest (macos-14, macos-15, macos-26). Standard GitHub-hosted runners are free and unlimited for public repositories; private repositories draw on the account's free minutes allotment and are then billed per minute. Scope: GitHub Actions. Reviewed October 4, 2026.
Choosing runners with runs-on
Document v1 · published by Koskamo editorial · updated 2026-10-04
Source and provenance
- Original source
- docs.github.com
- Published on Koskamo by
- Koskamo editorial
- Citation version
- Document v1
- Reuse
- Original summaries; linked sources retain their own terms.