GitHub Actions workflows often use a Linux runner without explicitly thinking about the operating system underneath it.

A workflow may simply contain:

runs-on: ubuntu-latest

That looks harmless, but ubuntu-latest is a moving label. It does not permanently point to one Ubuntu release. GitHub updates the label as runner images move to newer supported versions.

GitHub is preparing to move the x64 ubuntu-latest label to Ubuntu 26.04. The rollout is scheduled to begin on October 19, 2026, with the migration expected to complete by November 19, 2026. Until then, teams can explicitly use ubuntu-26.04 to test their workflows or use ubuntu-24.04 when they need to remain on Ubuntu 24.04.

For teams with important CI/CD pipelines, this is not simply an operating-system upgrade. A runner image contains compilers, SDKs, system libraries, package managers, command-line tools, and other preinstalled software.

That means an operating-system change can expose assumptions that were previously hidden in a workflow.

What Is Changing?

GitHub currently provides explicit Ubuntu runner labels including:

ubuntu-22.04
ubuntu-24.04
ubuntu-26.04

The ubuntu-latest label is moving to Ubuntu 26.04 as part of the migration. GitHub's runner documentation currently lists ubuntu-26.04 as an available x64 runner, with the standard public-repository runner providing 4 CPUs, 16 GB RAM, and 14 GB SSD.

The important distinction is:

Runner label

Behavior

ubuntu-24.04

Explicit Ubuntu 24.04

ubuntu-26.04

Explicit Ubuntu 26.04

ubuntu-latest

Follows GitHub's current latest stable Ubuntu image

This is why migration testing should happen before relying on ubuntu-latest.

Why an Ubuntu Runner Upgrade Can Break CI

A GitHub Actions workflow depends on more than the Ubuntu version.

For example:

steps:
  - uses: actions/checkout@v4

  - name: Install dependencies
    run: sudo apt-get update && sudo apt-get install -y build-essential

  - name: Build
    run: ./build.sh

  - name: Test
    run: ./test.sh

The workflow may depend on:

A runner-image migration can therefore expose compatibility problems even when the workflow YAML itself has not changed.

Ubuntu 26.04 Is Already Available as an Explicit Runner

Ubuntu 26.04 is available through the explicit:

runs-on: ubuntu-26.04

label.

GitHub's runner-images project currently identifies both x64 and Arm64 Ubuntu 26.04 images.

The Ubuntu 26.04 image is based on Ubuntu 26.04 LTS and currently uses a 7.0 Azure kernel and systemd 259.5. The installed software image also includes modern versions of tools such as Python, Node.js, Clang, npm, Ruby, and other development utilities.

The exact installed software should not be treated as a permanent contract, however. GitHub updates runner images regularly.

Step 1: Find Every Ubuntu Runner in Your Workflows

Before changing anything, search your repository for:

runs-on:

Pay particular attention to:

runs-on: ubuntu-latest

and:

runs-on: ubuntu-24.04

You should also check reusable workflows.

For example:

jobs:
  build:
    uses: ./.github/workflows/build.yml

The actual runner may be defined inside the reusable workflow rather than the calling workflow.

A simple inventory might look like this:

Workflow

Current Runner

Purpose

Risk

build.yml

ubuntu-latest

Build

Medium

test.yml

ubuntu-latest

Unit tests

Medium

release.yml

ubuntu-24.04

Package release

High

deploy.yml

ubuntu-latest

Deployment

High

This gives you a starting point for migration testing.

Step 2: Test With ubuntu-26.04

The safest first step is usually to create a migration branch and explicitly change:

runs-on: ubuntu-26.04

For example:

name: Build and Test

on:
  push:
  pull_request:

jobs:
  build:
    runs-on: ubuntu-26.04

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.x'

      - name: Restore
        run: dotnet restore

      - name: Build
        run: dotnet build --configuration Release --no-restore

      - name: Test
        run: dotnet test --configuration Release --no-build

This lets you test the new environment without waiting for ubuntu-latest to move.

GitHub specifically recommends using ubuntu-26.04 to test during the transition period.

Step 3: Test Your Toolchain Explicitly

Do not rely heavily on whatever happens to be preinstalled on the runner.

For example, if your application requires a specific .NET version, install that version explicitly:

- name: Setup .NET
  uses: actions/setup-dotnet@v4
  with:
    dotnet-version: '10.x'

For Node.js:

- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '22'

For Python:

- name: Setup Python
  uses: actions/setup-python@v6
  with:
    python-version: '3.13'

This makes the workflow less dependent on the runner image.

The goal is not to install everything manually. It is to explicitly control the versions that matter to your application.

Step 4: Look for System-Level Dependencies

This is one of the most important migration checks.

Search your workflows and scripts for commands such as:

apt-get
apt
dpkg
ldconfig
systemctl
gcc
g++
make
cmake
openssl
python
node
npm
docker

For example:

- name: Install native dependencies
  run: |
    sudo apt-get update
    sudo apt-get install -y \
      libssl-dev \
      zlib1g-dev \
      build-essential

The packages may still exist on Ubuntu 26.04, but package versions and system behavior can change.

If your application depends on a specific package version, verify it instead of assuming compatibility.

Step 5: Check OpenSSL and Native Libraries

Native dependencies are particularly important for applications that compile or load native libraries.

For example:

openssl version

can be useful during migration testing.

You can temporarily add diagnostic steps:

- name: Check environment
  run: |
    uname -a
    lsb_release -a
    openssl version
    gcc --version
    python --version
    node --version

This gives you evidence about the environment in which the workflow actually ran.

Once the migration is complete, unnecessary diagnostic commands can be removed.

Step 6: Check Docker-Based Workflows

Docker-based workflows should also be tested carefully.

For example:

- name: Build container
  run: docker build -t sample-api:ci .

If your workflow uses Docker Compose, Buildx, container actions, or custom scripts, run the complete pipeline on Ubuntu 26.04.

Do not stop after confirming that:

docker --version

works.

The important test is whether the actual build, test, packaging, and deployment process succeeds.

Step 7: Check Package Installation Scripts

A common source of migration problems is a script that assumes an older Ubuntu environment.

For example:

sudo apt-get update
sudo apt-get install -y some-package

This may work today but fail later if:

Review scripts that add external package repositories carefully.

Avoid silently trusting installation commands copied from older setup documentation.

Step 8: Check apt-key and Repository Configuration

Ubuntu migrations can also expose older package-management practices.

If your repository contains commands such as:

apt-key add

review them.

Newer Ubuntu environments have moved away from the older apt-key approach. Projects that maintain their own package repository setup should use a current, supported repository configuration.

The important point is not to copy an old installation script unchanged just because it worked on Ubuntu 24.04.

Step 9: Check Cgroup Assumptions

Container-heavy workflows should check whether their tooling makes assumptions about Linux cgroups.

Ubuntu 26.04 uses cgroup v2, and older tooling that expects cgroup v1 can require changes. This is particularly relevant to custom container tooling, older CI scripts, and software that directly interacts with Linux resource-control interfaces.

If your workflow does not interact with cgroups directly, this may not require any changes.

But if you have scripts that inspect paths such as:

/sys/fs/cgroup/

or depend on older container behavior, include them in your migration tests.

Step 10: Test Self-Hosted Runner Assumptions Separately

A workflow that works on GitHub-hosted Ubuntu 26.04 does not automatically prove that it works on every self-hosted Linux runner.

Self-hosted runners are controlled by the organization and can have different:

Keep GitHub-hosted runner migration testing separate from self-hosted infrastructure migration.

Use a Matrix to Compare Runner Versions

For important repositories, a temporary matrix can make migration testing easier.

jobs:
  test:
    strategy:
      matrix:
        os:
          - ubuntu-24.04
          - ubuntu-26.04

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '10.x'

      - name: Build
        run: dotnet build --configuration Release

      - name: Test
        run: dotnet test --configuration Release --no-build

This is useful because the same workflow executes against both environments.

You can then compare:

Ubuntu 24.04
     |
     +-- Build
     +-- Test
     +-- Package
     |
     v
Ubuntu 26.04
     |
     +-- Build
     +-- Test
     +-- Package

If one environment fails, you have a much clearer starting point for investigation.

Do Not Use ubuntu-latest as Your Migration Test

There is an important difference between:

runs-on: ubuntu-latest

and:

runs-on: ubuntu-26.04

When testing the migration, use the explicit version.

If you continue testing only with ubuntu-latest, the underlying runner can change independently of your migration work.

An explicit label gives you a known target.

Once your application works correctly on Ubuntu 26.04, you can decide whether to continue using:

runs-on: ubuntu-26.04

or return to:

runs-on: ubuntu-latest

The right choice depends on how much control you want over runner-version changes.

Pinning the Ubuntu Version vs Using latest

Approach

Benefit

Trade-off

ubuntu-latest

Automatically follows GitHub's latest stable Ubuntu image

Future image changes can affect workflows

ubuntu-24.04

Predictable Ubuntu version

Requires future migration planning

ubuntu-26.04

Explicitly adopts Ubuntu 26.04

You still need to manage future image changes

Matrix testing

Compares environments directly

Temporarily increases CI usage

For production-critical workflows, explicit runner labels can make migration timing easier to control.

For less sensitive workflows, ubuntu-latest can reduce manual maintenance.

Common Migration Problems

Missing Packages

A workflow may fail with:

E: Unable to locate package ...

Check whether the package is still available under the expected name and repository.

Native Binary Failures

You may see errors such as:

error while loading shared libraries

or:

GLIBC_... not found

These usually point toward compatibility between the binary and the system libraries.

Tool Version Differences

A script may expect a specific version:

node --version

while the runner contains another version.

Install the required version explicitly rather than relying on the image default.

Third-Party Repository Problems

A setup script may reference a repository that does not yet support Ubuntu 26.04.

Verify third-party dependencies independently before migrating the entire pipeline.

Container Compatibility

Older container tooling can behave differently under newer kernel and cgroup environments.

Test the actual container workflow rather than only checking that Docker starts.

Best Practices for the Migration

Test Explicitly

Use:

runs-on: ubuntu-26.04

during migration testing.

Pin Important Tool Versions

Explicitly configure language runtimes and SDKs where reproducibility matters.

Avoid Hidden Dependencies

If a build depends on a package, install or otherwise provision it deliberately rather than assuming it is present.

Keep Migration Changes Small

Do not combine an Ubuntu migration with a major application refactoring if you can avoid it.

If the build fails, you want to know which change caused the problem.

Test the Complete Pipeline

A successful compilation is not enough.

Test:

  1. Restore

  2. Build

  3. Unit tests

  4. Integration tests

  5. Packaging

  6. Container builds

  7. Security scanning

  8. Deployment steps where appropriate

Monitor After Migration

A workflow can pass during a test branch and still expose an edge case later.

Watch production CI runs after migration and investigate new failure patterns.

A Practical Migration Checklist

[ ] Find all ubuntu-latest workflows
[ ] Find all ubuntu-24.04 workflows
[ ] Check reusable workflows
[ ] Test with ubuntu-26.04
[ ] Pin important SDK/runtime versions
[ ] Review apt package installation
[ ] Check native libraries
[ ] Check OpenSSL dependencies
[ ] Test Docker workflows
[ ] Review third-party repositories
[ ] Check cgroup-related tooling
[ ] Run the complete test suite
[ ] Compare Ubuntu 24.04 and 26.04 where useful
[ ] Review deployment workflows separately
[ ] Decide whether to use an explicit runner or ubuntu-latest
[ ] Monitor CI after migration

Advantages and Disadvantages

Advantages

Disadvantages

Access to the newer Ubuntu LTS environment

Existing workflows may expose compatibility issues

Allows teams to test the future ubuntu-latest environment early

Migration requires CI testing

Explicit runner label provides predictable targeting

Third-party tools may need updates

Modern development tools are available

Native dependencies require careful validation

Can be tested without immediately changing ubuntu-latest

Large organizations may have many workflows to review

Summary

Moving GitHub Actions workflows to Ubuntu 26.04 should be treated as a CI environment migration rather than a simple one-line YAML change.

GitHub already provides the explicit ubuntu-26.04 runner, and the ubuntu-latest label is scheduled to transition to Ubuntu 26.04 through a rollout beginning October 19, 2026 and expected to complete by November 19, 2026.

The safest approach is to identify workflows that use Ubuntu runners, test them explicitly against ubuntu-26.04, verify system dependencies, pin important development tools, and test the complete CI/CD pipeline.

Pay particular attention to native libraries, package installation scripts, Docker workflows, third-party repositories, and tooling that depends on Linux kernel or cgroup behavior.

Most importantly, do not wait for ubuntu-latest to change before discovering compatibility problems. Testing with ubuntu-26.04 now gives teams a controlled environment in which to find and fix those problems before the automatic migration reaches their workflows.