7.4 Runner Groups, Labels & Organization Routing

Key Takeaways

  • Runner groups provide administrative and security access control boundaries at the organization and enterprise levels, restricting which repositories are authorized to execute jobs on specific runner pools.
  • Enterprise runner groups can be shared across all organizations or granted to selected organizations, while organization runner groups can be opened to all repositories or restricted to explicit repository lists.
  • Runner labels provide job routing metadata; when a workflow specifies multiple labels in `runs-on: [self-hosted, linux, x64, gpu]`, GitHub Actions applies strict Boolean AND matching logic requiring the runner to have ALL listed labels.
  • Default system labels (`self-hosted`, `linux`, `windows`, `macOS`, `x64`, `arm64`) are automatically assigned by the runner daemon based on OS and CPU architecture detection, while administrators assign custom labels for specialized capabilities.
  • Public repository access to runner groups is explicitly blocked by default (`allows_public_repositories = false`), preventing untrusted public code from accessing enterprise runner pools even if workflow labels match.
Last updated: August 2026

Runner Groups, Labels & Organization Routing

In enterprise environments with hundreds of repositories, dozens of development teams, and heterogeneous compute infrastructure, managing self-hosted runners individually becomes unmanageable. Unrestricted runner access can lead to security vulnerabilities (e.g., untrusted repositories executing code on production deployment runners) and resource starvation (e.g., frontend lint jobs consuming high-cost GPU machines).

GitHub Actions solves these governance and operational challenges through two complementary mechanisms: Runner Groups (which govern administrative access and repository permissions) and Runner Labels (which govern job routing and hardware targeting). Understanding their configuration, hierarchy, and Boolean matching logic is essential for enterprise platform engineers and the GH-200 certification.


1. Enterprise & Organization Runner Groups Architecture

A Runner Group is an administrative container used to manage collections of self-hosted runners or Larger Runners. Instead of configuring access permissions on individual machines, administrators place runners into groups and apply access control policies to the group as a whole.

+-----------------------------------------------------------------------------+
|                   ENTERPRISE & ORG RUNNER GROUP HIERARCHY                   |
|                                                                             |
|   ENTERPRISE ACCOUNT (e.g., 'octo-corp')                                    |
|   └── Enterprise Runner Group: "prod-pci-runners"                           |
|       ├── Policy: Access granted ONLY to Organization "payments-org"        |
|       └── Contains: 20x Bare-Metal High-Security Linux Servers              |
|                                                                             |
|   ORGANIZATION ACCOUNT (e.g., 'payments-org')                              |
|   └── Organization Runner Group: "production-deployers"                     |
|       ├── Policy: Access granted ONLY to Selected Repos:                    |
|       │   ├── 'payment-gateway'                                             |
|       │   └── 'auth-service'                                                |
|       └── Contains: Ephemeral ARC Kubernetes Runner ScaleSet                |
+-----------------------------------------------------------------------------+

Hierarchy & Scopes

  1. Enterprise Runner Groups: Configured at the Enterprise Account level (/enterprises/{enterprise}/settings/actions/runner-groups). Enterprise administrators use these to allocate runner pools across business units and control which organizations within the enterprise can access them.
    • Access options: "All organizations" or "Selected organizations".
  2. Organization Runner Groups: Configured at the Organization level (/orgs/{org}/settings/actions/runner-groups). Organization owners use these to manage runner pools across projects and control which repositories can access them.
    • Access options: "All repositories" or "Selected repositories".
  3. The Default Runner Group: Every organization and enterprise possesses a built-in group named Default. When a new self-hosted runner is registered without specifying --runnergroup, it is automatically placed in the Default group.

2. Access Control Policies & Security Restrictions

Runner groups act as security firewalls between repositories and compute infrastructure. Platform teams enforce least-privilege execution using three primary access controls:

┌─────────────────────────────────────────────────────────────────────────────┐
│                     RUNNER GROUP ACCESS POLICY MATRIX                       │
│                                                                             │
│  1. REPOSITORY ACCESS POLICY:                                               │
│     ( ) All repositories (Permissive - All repos in org can target group)   │
│     (*) Selected repositories (Restricted - Only explicitly chosen repos)   │
│                                                                             │
│  2. PUBLIC REPOSITORY SAFETY GATE:                                          │
│     [ ] Allow public repositories (DEFAULT: OFF - Blocks untrusted PRs)     │
│                                                                             │
│  3. WORKFLOW PERMISSION POLICY (Enterprise):                                │
│     (*) Allow all workflows                                                 │
│     ( ) Allow selected reusable workflows only (Enforces golden paths)      │
└─────────────────────────────────────────────────────────────────────────────┘

Critical Access Controls

  • Selected Repositories Allowlisting: High-privilege runners (such as runners with production network access or deployment credentials) should be placed in a dedicated runner group restricted strictly to production deployment repositories. Untrusted or experimental repositories are blocked from dispatching jobs to these runners, even if their workflow YAML specifies matching labels.
  • Public Repository Security Gate: The setting "Allow public repositories" is disabled by default. Even if a public repository belongs to an organization with access to the runner group, GitHub Actions will block workflows in that public repository from using the group's runners unless an administrator explicitly enables this setting.
  • Workflow Restrictions (Enterprise): Enterprise administrators can restrict a runner group so that only approved reusable workflows defined in a centralized governance repository (e.g., octo-corp/secure-workflows/.github/workflows/deploy.yml@v1) can execute on those runners.

3. Default vs. Custom Runner Labels

While runner groups determine which repositories are authorized to use a runner, Runner Labels determine which specific machine within the authorized pool executes a given job.

+-----------------------------------------------------------------------------+
|                        RUNNER LABEL CLASSIFICATION                          |
|                                                                             |
|   DEFAULT (SYSTEM) LABELS                CUSTOM LABELS                      |
|   (Assigned automatically by daemon)     (Assigned by Admin / config.sh)    |
|                                                                             |
|   • self-hosted (Mandatory)              • gpu / nvidia-a100                |
|   • linux / windows / macOS              • high-memory / 256gb-ram          |
|   • x64 / arm64 / arm                    • production-vpc / dmz             |
|                                          • xcode-16 / android-sdk-34        |
+-----------------------------------------------------------------------------+

Default (System) Labels

When the self-hosted runner application is initialized via ./config.sh, it detects the local operating system and CPU architecture and automatically assigns three immutable system labels:

  1. self-hosted: Assigned to every self-hosted runner.
  2. Operating System Label: linux, windows, or macOS.
  3. Architecture Label: x64, arm64, or arm.

Custom Labels

Administrators assign custom labels to represent specialized hardware, compliance boundaries, network zones, or installed toolchains. Custom labels can be assigned:

  • Via ./config.sh parameter: --labels "gpu,production-dmz,high-memory"
  • Via GitHub Web UI: Settings → Actions → Runners → [Select Runner] → Labels
  • Via REST API: POST /orgs/{org}/actions/runners/{runner_id}/labels

4. Job Routing Logic: Multi-Label Boolean AND Matching

When a workflow job defines the runs-on: attribute, GitHub Actions executes a deterministic multi-step routing algorithm to locate an eligible runner.

                HOW GITHUB ACTIONS ROUTES JOBS TO RUNNERS

 1. Job Queued in Repository 'my-org/payment-service'
                           │
                           ▼
 2. Evaluate Runner Groups: Does 'payment-service' have access to
    the specified Runner Group (or the Default group)?
                           │
                          YES
                           │
                           ▼
 3. Evaluate Label Matching: Compare runs-on array with Runner Labels
    Workflow: runs-on: [self-hosted, linux, gpu, production-vpc]
                           │
                           ▼
 4. Boolean AND Logic: Does candidate runner have ALL 4 labels?

    • Runner 1: [self-hosted, linux, x64]                --> ❌ REJECTED (Missing gpu, production-vpc)
    • Runner 2: [self-hosted, linux, gpu, x64]           --> ❌ REJECTED (Missing production-vpc)
    • Runner 3: [self-hosted, linux, gpu, production-vpc, x64] --> ✅ ACCEPTED & ASSIGNED!

Strict Boolean AND Matching Rule

In GitHub Actions, specifying multiple labels in runs-on: represents a logical AND condition, not an OR condition:

  • runs-on: [self-hosted, linux, gpu]: The runner must possess the self-hosted label AND the linux label AND the gpu label.
  • If a runner possesses [self-hosted, linux, x64] but lacks gpu, it cannot pick up the job.
  • A runner that possesses additional labels beyond those requested (e.g., [self-hosted, linux, gpu, x64, fast-disk]) can pick up the job, provided it possesses every label listed in the workflow runs-on array.

5. Workflow Targeting Syntax & Best Practice Examples

GitHub Actions supports targeting runners by labels, runner groups, or a combination of both.

Pattern A: Standard Multi-Label Targeting

name: ML Model Training Pipeline
on:
  push:
    branches: [main]

jobs:
  train-model:
    # Runner must match ALL three labels
    runs-on: [self-hosted, linux, gpu]
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Verify GPU CUDA Availability
        run: nvidia-smi

Pattern B: Explicit Runner Group + Label Targeting

To guarantee that a job runs strictly within a specific administrative group (avoiding accidental matching on another group that happens to have the same labels), specify both group: and labels::

name: Production Deployment
on:
  push:
    tags: ['v*']

jobs:
  deploy-prod:
    runs-on:
      group: production-secure-runners
      labels: [self-hosted, linux, production-vpc]
    steps:
      - name: Checkout Deployment Code
        uses: actions/checkout@v4

      - name: Execute Deployment Script
        run: ./scripts/deploy-production.sh

Pattern C: Multi-Platform Matrix Targeting Hosted & Self-Hosted Pools

name: Polyglot Build Matrix
on: [push]

jobs:
  build:
    strategy:
      matrix:
        include:
          - target: standard-linux
            os: ubuntu-latest
          - target: custom-arm
            os: [self-hosted, linux, ARM64]
          - target: enterprise-gpu
            os: [self-hosted, linux, gpu]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Print Architecture
        run: uname -m
Loading diagram...
Runner Group Authorization Hierarchy and Multi-Label Job Matching Flow
Test Your Knowledge

A workflow defines runs-on: [self-hosted, linux, high-memory]. The organization has three active self-hosted runners with the following assigned labels:

  • Runner 1: [self-hosted, linux, x64]
  • Runner 2: [self-hosted, linux, high-memory, arm64]
  • Runner 3: [self-hosted, windows, high-memory]
Which runner(s) can pick up and execute the workflow job?

A
B
C
D
Test Your Knowledge

An enterprise security administrator wants to prevent non-production and experimental repositories from executing jobs on a pool of self-hosted runners configured with direct network access to the production datacenter. What is the recommended GitHub Actions governance mechanism to enforce this isolation?

A
B
C
D
Test Your Knowledge

An enterprise administrator creates a new self-hosted runner group at the enterprise level. What is the default access setting for public repositories, and what happens if a public repository within an authorized organization attempts to route a job to runners in this group?

A
B
C
D