Create, manage, and use custom images for GitHub-hosted larger runners in your organization or enterprise.
You can create a custom image to define the exact environment that your GitHub-hosted larger runners use. Custom images let you preinstall tools, dependencies, and configurations to speed up workflows and improve consistency across jobs.
When your runner uses a custom image, it acts as a “pre-warmed” environment, allowing workflows to complete quicker, by downloading packages and binaries once during image creation instead of every time a workflow is run. For more information about custom images, see Runner images.
The process of using a custom image involves three main steps:
Before you can create custom images, make sure the following requirements are met.
Policy: Custom images must be enabled for your organization or enterprise. Enterprise owners can manage access to custom images and set retention policies in the Actions policy settings. For more information, see Enforcing policies for GitHub Actions in your enterprise.
Permissions: To create and manage custom images, you must be an organization or enterprise owner, or have the CI/CD Admin role, or have a role with the following fine-grained permissions.
For more information, see Permissions of custom organization roles.
To create a custom image, you must first set up an image-generation runner. When you create the runner, the platform that you select for your runner must match the platform of the image you want to build. The platform of the runner can be Linux x64, Linux ARM64, or Windows x64.
After you create an image-generation runner, run a workflow that includes the snapshot keyword to generate a custom image.
To configure a workflow for image generation:
runs-on value to the name of the image-generation runner that you created.snapshot keyword to the job, using either the string syntax or mapping syntax shown below.
snapshot keyword creates a separate image. To generate only one image or image version, include all workflow steps in a single job.snapshot keyword creates a new version of that image.Note
GitHub recommends configuring image generation as a scheduled workflow on a weekly basis. This approach ensures dependencies remain up-to-date and have the latest security patches. For more information, see Events that trigger workflows.
It can take some time for your image to be fully generated and ready to use after the workflow completes. Provisioning time varies based on runner size and configuration, and may take several hours for larger runners.
The image is generated only when the job completes successfully. This prevents new image versions from being created when a workflow fails or ends in an incomplete state.
Once the image is generated, it is available for use in your workflows. For more information about managing custom images, see Managing custom images.
You can use the string syntax with snapshot to define the image name. This method creates a new image or adds a new version to an existing image with the same name. You cannot specify a version number using this syntax.
jobs:
build:
runs-on: my-image-generation-runner
snapshot: my-custom-image
steps:
# Add any steps to download and setup any dependencies here
You can use the mapping syntax with snapshot to define both the image-name and the optional version. When you specify a major version, the minor versioning automatically increments if that major version already exists. Patch versions are not supported.
jobs:
build:
runs-on: my-image-generation-runner
snapshot:
image-name: my-custom-image
version: 2.*
steps:
# Add any steps to download and setup any dependencies here
When you generate custom images, GitHub automatically assigns version numbers to help you manage updates and track image history.
If an image with the specified name does not exist in your organization or enterprise, GitHub creates it with an initial version number of 1.0.0.
If an image with the same name already exists, GitHub creates a new version by incrementing the minor version number (for example, 1.1.0, 1.2.0, etc.).
If you do not specify a version in your YAML file, image generation uses this default behavior.
If you include a version in the YAML mapping, GitHub checks the major version number first.
Patch versions are not supported.
The most recent workflow run for an image is always tagged as latest.
If you specify an older major version in the YAML (for example, version: 1.* when a 2.0 version exists), GitHub generates a new minor version under the older major version and marks it as latest.
Note
GitHub-hosted larger runner creation does not support wildcards in image version selection.
Jobs that use custom images are billed at the same per-minute rate as the larger runner that uses the image. Storage for custom images is billed separately through GitHub Actions storage.
If you rebuild images frequently and retain older versions, your storage usage can grow quickly because each successful workflow job that includes the snapshot keyword creates a new image version. For more information, see GitHub Actions billing and Enforcing policies for GitHub Actions in your enterprise.
You can view detailed information about each image, delete unused images or specific versions, and track image versions over time.
On GitHub, navigate to the main page of the organization.
Under your organization name, click Settings. If you cannot see the "Settings" tab, select the dropdown menu, then click Settings.

In the left sidebar, click Actions, then click Custom images.
On the "Custom images" page, you can view all custom images that have been created in your organization or enterprise.
To view details about a specific image, click the image name.
Once your custom image is ready, you can install it on a new GitHub-hosted larger runner.
Follow the steps for creating a larger runner:
When configuring the runner:
In your GitHub Actions workflow job, set the runs-on key to the name of your runner.
jobs:
build:
runs-on: my-custom-runner
steps:
# Add any steps for your workflow here
Run your workflow to verify that it completes successfully. The job logs will show the image name and version in the "Set up job" section.
To prevent unauthorized changes to your images, follow these best practices.
write access for repositories that have access to image-generation runners. Because images can be generated from any branch, anyone with write access could create a branch with arbitrary code and trigger image generation.