Note: This is a custom fork of the GitHub Actions Runner Images repository. This fork includes customizations for building and managing Ubuntu runner images in Azure using Terraform infrastructure and automated GitHub Actions workflows.
Table of Contents
- About This Fork
- Custom Features
- Quick Start
- Terraform Infrastructure
- GitHub Actions Workflow
- Available Images
- Image Definitions
- Software and Image Support
- How to Interact with the Repo
- FAQs
This repository is a fork of the official GitHub Actions Runner Images repository, customized to build and manage Ubuntu runner images in Azure. The fork includes:
- Terraform Infrastructure: Automated provisioning of Azure Compute Gallery, user-assigned managed identity, and federated identity credentials for secure OIDC authentication
- Custom GitHub Actions Workflow: Automated image building and validation workflow that uses OIDC authentication
- Custom Image Definitions: Pre-configured image definitions for Ubuntu 22.04 and 24.04 in Azure Compute Gallery
This fork maintains compatibility with the upstream repository while adding infrastructure-as-code capabilities and automated CI/CD for image building.
The terraform/ directory contains infrastructure code to provision:
- Azure Compute Gallery (Shared Image Gallery): Centralized repository for versioned VM images
- User-Assigned Managed Identity: Identity used by Packer for Azure authentication
- Federated Identity Credential: OIDC-based authentication for GitHub Actions workflows
- Resource Groups: Separate resource groups for images, build resources, and networking
- Role Assignments: Proper RBAC permissions for the managed identity
The .github/workflows/build_custom_ubuntu_runner_image.yaml workflow provides:
- Automated Image Building: Triggered manually via
workflow_dispatch - OIDC Authentication: Secure authentication to Azure without storing secrets
- Packer Integration: Automated Packer template validation and image building
- Version Management: Automatic versioning based on GitHub run numbers
- Multi-Image Support: Matrix strategy for building multiple Ubuntu versions
- Azure Subscription: An active Azure subscription with appropriate permissions
- GitHub Repository: This repository with GitHub Actions enabled
- Terraform: Version >= 1.9.0, < 2.0.0
- Azure CLI: For authentication and resource management
-
Navigate to the
terraform/directory:cd terraform -
Create a
terraform.tfvarsfile with your configuration:subscription_id = "your-subscription-id" location = "switzerlandnorth" name = "your-gallery-name" image_resource_group_name = "rg-images" build_resource_group_name = "rg-build" network_resource_group_name = "rg-network" github_repo = "your-org/your-repo" github_branch = "refs/heads/main" publisher = "YourOrganization"
-
Initialize and apply Terraform:
terraform init terraform plan terraform apply
-
Note the output values, especially
workload_identity_client_id:terraform output workload_identity_client_id
Add the following secrets to your GitHub repository:
AZURE_CLIENT_ID: The client ID from the Terraform output (workload_identity_client_id)AZURE_TENANT_ID: Your Azure tenant IDAZURE_SUBSCRIPTION_ID: Your Azure subscription IDIMAGE_RESOURCE_GROUP: The resource group name where images are stored (e.g.,rg-images)BUILD_RG_NAME: The resource group name for build resources (e.g.,rg-build)
Update the workflow file .github/workflows/build_custom_ubuntu_runner_image.yaml with your specific values:
GALLERY_NAME: Your Azure Compute Gallery nameLOCATION: Your Azure region- Matrix configuration for the images you want to build
- Go to the Actions tab in your GitHub repository
- Select Build Custom Ubuntu Runner Image
- Click Run workflow
- Monitor the workflow execution
The built images will be available in your Azure Compute Gallery and can be used to create VMs or scale sets.
The Terraform configuration in the terraform/ directory provisions all necessary Azure resources for building and storing runner images.
azurerm_resource_group.images: Resource group for storing images and the compute galleryazurerm_resource_group.build: Resource group for temporary build resourcesazurerm_user_assigned_identity.identity: Managed identity for authenticationazurerm_federated_identity_credential.github: OIDC credential for GitHub Actionsmodule.compute_gallery: Azure Compute Gallery with image definitions
The Terraform configuration includes pre-defined image definitions for:
- Ubuntu 22.04 LTS:
github-runner-ubuntu-2204 - Ubuntu 24.04 LTS:
github-runner-ubuntu-2404
Each definition includes:
- OS type and architecture
- Hyper-V generation
- Recommended VM sizes
- End-of-life dates
- Metadata tags
To customize the infrastructure:
- Modify
terraform/variables.tfto add or change variables - Update
terraform/main.tfto add additional image definitions or resources - Adjust the
shared_image_definitionsin the compute gallery module
The Terraform configuration outputs:
workload_identity_client_id: The client ID of the managed identity (required for GitHub secrets)
The build_custom_ubuntu_runner_image.yaml workflow automates the image building process:
- Checkout: Retrieves the repository code
- Azure Login: Authenticates using OIDC (no secrets required)
- Packer Setup: Installs and configures Packer
- Validation: Validates Packer templates before building
- Build: Executes Packer to build the VM image
- Publish: Publishes the image to Azure Compute Gallery
Key environment variables in the workflow:
GALLERY_NAME: Name of your Azure Compute GalleryLOCATION: Azure region for resourcesPACKER_VERSION: Packer version to useIMAGE_VERSION: Version format (e.g.,1.0.{run_number})
The workflow uses a matrix strategy to build multiple images. Currently configured for:
- Ubuntu 24.04 (
ubuntu24)
To add Ubuntu 22.04, uncomment the relevant lines in the matrix configuration.
The workflow requires:
contents: read: To checkout the repositoryid-token: write: For OIDC authentication
The workflow is triggered manually via workflow_dispatch. To build images:
- Navigate to Actions → Build Custom Ubuntu Runner Image
- Click "Run workflow"
- Select the branch (usually
main) - Click "Run workflow"
This repository contains the source code used to create the VM images for GitHub-hosted runners used for Actions, as well as for Microsoft-hosted agents used for Azure Pipelines.
For detailed information on building images manually, see the instructions.
| Image | YAML Label | Included Software |
|---|---|---|
| Ubuntu 24.04 | ubuntu-latest or ubuntu-24.04 |
ubuntu-24.04 |
| Ubuntu 22.04 | ubuntu-22.04 |
ubuntu-22.04 |
| Ubuntu Slim | ubuntu-slim |
ubuntu-slim |
macOS 26 Arm64 beta |
macos-26 or macos-26-xlarge |
macOS-26-arm64 |
| macOS 15 | macos-latest-large, macos-15-large, or macos-15-intel |
macOS-15 |
| macOS 15 Arm64 | macos-latest, macos-15, or macos-15-xlarge |
macOS-15-arm64 |
| macOS 14 | macos-14-large |
macOS-14 |
| macOS 14 Arm64 | macos-14 or macos-14-xlarge |
macOS-14-arm64 |
| Windows Server 2025 | windows-latest or windows-2025 |
windows-2025 |
| Windows Server 2022 | windows-2022 |
windows-2022 |
| Windows Server 2019 |
windows-2019 |
windows-2019 |
- In general the
-latestlabel is used for the latest OS image version that is GA - Before moving the
-latestlabel to a new OS version we will announce the change and give sufficient lead time for users to update their workflows
The purpose of a Beta is to collect feedback on an image before it is released to GA. The goal of a Beta is to identify and fix any potential issues that exist on that image. Images are updated on a weekly cadence. Any workflows that run on a beta image do not fall under the customer SLA in place for Actions. Customers choosing to use Beta images are encouraged to provide feedback in the runner-images repo by creating an issue. A Beta may take on different availability, i.e. public vs private.
A GA (General Availability) image has been through a Beta period and is deemed ready for general use. Images are updated on a weekly cadence. In order to be moved to GA the image must meet the following criteria:
- Has been through a Beta period (public or private)
- Most major software we install on the image has a compatible version for the underlying OS and
- All major bugs reported during the Beta period have been addressed.
This image type falls under the customer SLA for actions. GA images are eventually deprecated according to our guidelines as we only support the latest 2 versions of an OS.
GitHub Actions and Azure DevOps use the -latest YAML label (ex: ubuntu-latest, windows-latest, and macos-latest). These labels point towards the newest stable OS version available.
The -latest migration process is gradual and happens over 1-2 months in order to allow customers to adapt their workflows to the newest OS version. During this process, any workflow using the -latest label, may see changes in the OS version in their workflows or pipelines. To avoid unwanted migration, users can specify a specific OS version in the yaml file (ex: macos-14, windows-2022, ubuntu-22.04).
Images are built on-demand using the GitHub Actions workflow. Each build creates a new version in the Azure Compute Gallery with the format 1.0.{run_number}.
To track image builds:
- Monitor the GitHub Actions workflow runs
- Check the Azure Compute Gallery for new image versions
- Review the workflow logs for build details and any issues
Note: This fork builds images independently from the upstream repository. For information about upstream releases, see the original repository.
-
Tools and versions will typically be removed 6 months after they are deprecated or have reached end-of-life
-
We support (at maximum) 2 GA images and 1 beta image at a time. We begin the deprecation process of the oldest image label once the newest OS image label has been released to GA.
-
The images generally contain the latest versions of packages installed except for Ubuntu LTS where we mostly rely on the Canonical-provided repositories.
-
Popular tools can have several versions installed side-by-side with the following strategy:
| Tool name | Installation strategy |
|---|---|
| Docker images | not more than 3 latest LTS OS\tool versions. New images or new versions of current images are added using the standard tool request process |
| Java | all LTS versions |
| Node.js | 3 latest LTS versions |
| Go | 3 latest minor versions |
| Python Ruby |
5 most popular major.minor versions |
| PyPy | 3 most popular major.minor versions |
| .NET Core | 2 latest LTS versions and 1 latest version. For each feature version only latest patch is installed. Note for Ubuntu images see details. |
| GCC GNU Fortran Clang GNU C++ |
3 latest major versions |
| Android NDK | 1 latest non-LTS, 2 latest LTS versions |
| Xcode | - only one major version of Xcode will be supported per macOS version - all minor versions of the supported major version will be available - beta and RC versions will be provided "as-is" in the latest available macOS image only no matter of beta/GA status of the image - when a new patch version is released, the previous patch version will be replaced |
| Xcode Platforms | - only three major.minor versions of platform tools and simulator runtimes will be available for installed Xcode, including beta/RC versions |
We use third-party package managers to install software during the image generation process. The table below lists the package managers and the software installed.
Note
Third-party repositories are re-evaluated every year to identify if they are still useful and secure.
| Operating system | Package manager | Third-party repos and packages |
|---|---|---|
| Ubuntu | APT | docker Eclipse-Temurin (Adoptium) Erlang Firefox git-lfs git Google Cloud CLI Heroku HHvm MongoDB Mono MS Edge PostgreSQL R |
| pipx | ansible-core yamllint |
|
| Windows | Chocolatey | No third-party repos installed |
| macOS | Homebrew | aws-cli v2 azure/bicep mongodb/brew |
| pipx | yamllint |
- Images begin the deprecation process of the oldest image label once a new GA OS version has been released.
- Deprecation process begins with an announcement that sets a date for deprecation
- As it gets closer to the date, GitHub begins doing scheduled brownouts of the image
- During this time there will be an Announcement pinned in the repo to remind users of the deprecation.
- Finally GitHub will deprecate the image and it will no longer be available
In general, these are the guidelines we follow when deciding what to pre-install on our images:
- Popularity: widely-used tools and ecosystems will be given priority.
- Latest Technology: recent versions of tools will be given priority.
- Deprecation: end-of-life tools and versions will not be added.
- Licensing: MIT, Apache, or GNU licenses are allowed.
- Time & Space on the Image: we will evaluate how much time is saved and how much space is used by having the tool pre-installed.
- Support: If a tool requires the support of more than one version, we will consider the cost of this maintenance.
- In general, once a new version is installed on the image, we announce the default version update 2 weeks prior to deploying it.
- For potentially dangerous updates, we may extend the timeline up to 1 month between the announcement and deployment.
This is a custom fork, so interaction is limited to this repository:
- Issues: Use this repository's issue tracker for bug reports or feature requests specific to this fork
- Pull Requests: Contributions to this fork are welcome
- Upstream Issues: For issues related to the upstream runner-images project, please use the original repository
- General Questions: For general questions about GitHub Actions or runner images, see the GitHub Actions Community Forum
What images are available for GitHub Actions and Azure DevOps?
The availability of images for GitHub Actions and Azure DevOps is the same. However, deprecation policies may differ. See documentation for more details:
What image version is used in my build?
Usually, image deployment takes 2-3 days, and documentation in the main branch is only updated when deployment is finished. To find out which image version and what software versions are used in a specific build, see Set up job (GitHub Actions) or Initialize job (Azure DevOps) step log.

Looking for other Linux distributions?
We do not plan to offer other Linux distributions. We recommend using Docker if you'd like to build using other distributions with the hosted runner images. Alternatively, you can leverage self-hosted runners and fully customize your VM image to your needs.
How do I contribute to the macOS source?
macOS source lives in this repository and is available for everyone. However, macOS image-generation CI doesn't support external contributions yet so we are not able to accept pull-requests for now.
We are in the process of preparing macOS CI to accept contributions. Until then, we appreciate your patience and ask you to continue to make tool requests by filing issues.
How does GitHub determine what tools are installed on the images?
For some tools, we always install the latest at the time of the deployment; for others, we pin the tool to specific version(s). For more details please see the Preinstallation Policy
How do I request that a new tool be pre-installed on the image?
Please create an issue and get an approval from us to add this tool to the image before creating the pull request.What branch should I use to build custom image?
We strongly encourage building images using the main branch. This repository contains multiple branches and releases that serve as document milestones to reflect what software is installed in the images at certain point of time. Current builds are not idempotent and if one tries to build a runner image using the specific tag it is not guaranteed that the build will succeed.For this fork, use the GitHub Actions workflow which builds from the branch you select when triggering the workflow.
How do I customize the image definitions?
To customize image definitions:- Add new image definitions: Edit
terraform/main.tfand add entries to theshared_image_definitionsmap in the compute gallery module - Modify existing definitions: Update the existing entries in
terraform/main.tf - Update workflow matrix: Add or modify entries in
.github/workflows/build_custom_ubuntu_runner_image.yamlmatrix strategy - Customize toolset: Modify the toolset JSON files in
images/ubuntu/toolsets/to change installed software
After making changes, run terraform plan and terraform apply to update the infrastructure, then trigger the workflow to build new images.
How do I use the built images?
Once images are built and published to your Azure Compute Gallery, you can:- Create VMs directly: Use Azure Portal, CLI, or Terraform to create VMs from the gallery images
- Use in VM Scale Sets: Reference the gallery image in your scale set configuration
- Share with other subscriptions: Configure gallery sharing in Terraform to share images across subscriptions or tenants
To reference an image, use:
- Gallery name: From your Terraform configuration
- Image definition: e.g.,
github-runner-ubuntu-2404 - Image version: e.g.,
1.0.123(from the workflow run number)
To keep this fork up-to-date with the upstream repository:
-
Add upstream remote (if not already added):
git remote add upstream https://github.com/actions/runner-images.git
-
Fetch upstream changes:
git fetch upstream
-
Merge upstream changes:
git checkout main git merge upstream/main
-
Resolve conflicts: If conflicts occur, resolve them carefully, especially in:
images/ubuntu/directories (image build scripts).github/workflows/(if you want to keep upstream workflows)terraform/(your custom infrastructure - likely no conflicts)
-
Test after syncing: After syncing, test the workflow to ensure images still build correctly
When syncing with upstream, be careful to preserve:
terraform/directory (entire directory is custom).github/workflows/build_custom_ubuntu_runner_image.yaml(custom workflow)- Any modifications to Packer templates in
images/ubuntu/templates/ - Custom toolset configurations in
images/ubuntu/toolsets/
This fork is based on the GitHub Actions Runner Images repository. For issues, discussions, or contributions related to the upstream project, please use the original repository.
License: This fork maintains the same license as the upstream repository. See LICENSE for details.