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 |
|---|---|
| Explicit Ubuntu 24.04 |
| Explicit Ubuntu 26.04 |
| 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:
system packages
compiler versions
OpenSSL behavior
Python versions
Node.js versions
Docker behavior
package-manager behavior
shell behavior
filesystem permissions
kernel features
preinstalled tools
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 | Medium |
|
| Unit tests | Medium |
|
| Package release | High |
|
| 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:
the package name changes
a repository changes
a package is removed
an installation script expects older libraries
a third-party repository does not yet support the new Ubuntu release
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:
operating systems
kernels
installed packages
architectures
Docker configurations
security policies
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 |
|---|---|---|
| Automatically follows GitHub's latest stable Ubuntu image | Future image changes can affect workflows |
| Predictable Ubuntu version | Requires future migration planning |
| 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:
Restore
Build
Unit tests
Integration tests
Packaging
Container builds
Security scanning
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 | 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 | 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.

Join the conversation! Your thoughts help the community grow.