Repository configuration
RunsOn supports describing various options through a configuration file. This file is located at .github/runs-on.yml (must be named exactly that) in the repository where you are using RunsOn runners.
The configuration file supports defining:
- custom images
- custom runners
- runner pools for faster job pickup times
- the list of admins having SSH access to the runners
- a global configuration file to extend from
Structure
Section titled “Structure”The configuration file is a YAML file with the following top-level keys: _extends, runners, images, pools, and admins.
_extends: ...runners: {...}images: {...}pools: {...}admins: [...string]_extends
Section titled “_extends”If set, the configuration file will inherit from the configuration file in the repository specified by the _extends value.
A common use case is to define a global configuration file in the .github-private repository of your organization, and then inherit from it in other repositories. Do not forget to allow the RunsOn GitHub App to access the repository hosting the global configuration file.
Example
Section titled “Example”_extends: .github-private
runners: ...In this example, the configuration file in the repository will inherit from the configuration file stored at .github/runs-on.yml in the .github-private repository.
runners
Section titled “runners”Mapping of custom runner names to runner configuration.
Available configuration options: cpu, ram, disk, family, spot, image, ssh, extras, private, retry, preinstall, tags.
For more details about each option, please refer to the job-level labels documentation.
Example
Section titled “Example”runners: docker_with_ipv6: cpu: [2, 4] ram: [2, 8] disk: default family: ["c7", "m7", "r7"] spot: capacity-optimized tags: - custom-tag-key1:custom-tag-value1 - custom-tag-key2-no-value preinstall: | cat > /etc/docker/daemon.json <<EOF { "ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64" } EOF systemctl restart docker
other-runner: ...And the runner will be available for use in the repository:
jobs: test: runs-on: runs-on=${{ github.run_id }}/runner=docker_with_ipv6runners.family
Section titled “runners.family”Required. Array of strings. e.g ["c7", "m7"].
runners.image
Section titled “runners.image”Required. String. e.g ubuntu22-full-x64.
runners.cpu
Section titled “runners.cpu”Array of integers. e.g [2, 4].
runners.ram
Section titled “runners.ram”Array of integers. e.g [2, 8].
runners.disk
Section titled “runners.disk”String. e.g default.
runners.spot
Section titled “runners.spot”Boolean or string. e.g capacity-optimized, co, lowest-price, lp, price-capacity-optimized, pco, true, false.
runners.ssh
Section titled “runners.ssh”Boolean. e.g true, false.
runners.extras
Section titled “runners.extras”Array of strings. e.g ["s3-cache"].
runners.private
Section titled “runners.private”Boolean. e.g true, false.
runners.retry
Section titled “runners.retry”String. e.g when-interrupted, false.
runners.preinstall
Section titled “runners.preinstall”String. Script to run on the runner, before the GitHub Actions runner agent is executed (see images.preinstall for more details).
runners.tags
Section titled “runners.tags”Array of strings containing custom key:value tags to apply to the runner underlying EC2 instance. e.g. ["custom-tag-key1:custom-tag-value1", "custom-tag-key2-no-value"].
Cannot start with the runs-on- prefix. Tag keys and values will be automatrically sanitized to remove any special characters (/ is allowed for values).
images
Section titled “images”Mapping of custom image names to image configuration.
Available configuration options: name, ami, platform, arch, owner, preinstall, tags.
Example
Section titled “Example”images: custom: owner: "123456789" name: "my-org/my-image-name-*" arch: x64 platform: linux tags: # filter with specific value is-production-ready: "true" # allow any value other-tag: "*"
fixed-ami: ami: "ami-0abcd159cbfafefgh"And you can use the image in your workflows like this:
jobs: test: runs-on: runs-on=${{ github.run_id }}/image=custom # or runs-on: runs-on=${{ github.run_id }}/image=fixed-amiimages.name
Section titled “images.name”Required (unless ami is set). String. Can include wildcards, in which case RunsOn will pick the most recent image matching the pattern.
images.ami
Section titled “images.ami”Required (unless name is set). String. If set, the image will be pinned to the specified AMI, irrespective of the name option.
images.platform
Section titled “images.platform”String. Either linux or windows. Not required if ami is set.
images.arch
Section titled “images.arch”String. Either x64 or arm64. Not required if ami is set.
images.owner
Section titled “images.owner”String. AWS account ID where the image is hosted.
images.preinstall
Section titled “images.preinstall”String. Script to run on the runner, before the GitHub Actions runner agent is executed. Takes precedence over the preinstall option at the runner level if both are set.
Useful to perform pre-authentication steps, such as logging into private registries. Installing additional software will make your runner boot time slower, it is recommended that you create your own AMI instead.
If the preinstall script fails, the job will fail. You will find the preinstall exit status and logs in the “Set up runner” section of the job logs.
Platform behaviour:
-
On Linux, the preinstall script is executed as the
rootuser, before the GitHub Actions runner agent is launched. The script must be a valid bash script, and will be executed withbash -e(so any failure will fail the script immediately). -
This option is not yet available for Windows images.
images.tags
Section titled “images.tags”Mapping of key-value tags to filter the image when searching for it.
Mapping of pool names to pool configurations. Pools allow you to pre-provision runners that stay warmed up and ready to pick up jobs immediately, reducing queue times from ~25 seconds (cold-start) to under 6 seconds for hot instances.
For comprehensive documentation about pools, see the Runner pools guide.
Available configuration options: env, runner, timezone, schedule.
Example
Section titled “Example”runners: small-x64: image: ubuntu24-full-x64 ram: 1 family: [t3] volume: gp3:30gb:125mbps:3000iops
pools: small-x64: env: production runner: small-x64 timezone: "America/New_York" schedule: - name: business-hours match: day: ["monday", "tuesday", "wednesday", "thursday", "friday"] time: ["08:00", "18:00"] stopped: 5 hot: 2 - name: default stopped: 2 hot: 1And you can use the pool in your workflows like this:
jobs: test: runs-on: runs-on/pool=small-x64pools.env
Section titled “pools.env”String. The stack environment this pool belongs to (e.g., production, dev). This ensures the pool only serves jobs targeting that environment.
pools.runner
Section titled “pools.runner”Required. String. Reference to a runner definition in the runners section. The pool will create instances matching this runner specification.
pools.timezone
Section titled “pools.timezone”String. IANA timezone for schedule calculations (e.g., America/New_York, Europe/Paris). Defaults to UTC if not specified.
pools.schedule
Section titled “pools.schedule”Required. Array of schedule rules. Each rule defines target capacity (hot/stopped instances) for specific time periods.
Schedule rule fields:
name: Human-readable name for this schedulematch.day: Array of days when this schedule applies (e.g.,["monday", "tuesday"])match.time: Time range[start, end]in 24-hour format (e.g.,["08:00", "18:00"])stopped: Number of stopped instances to maintain (pre-warmed but not running)hot: Number of hot instances to maintain (running and ready)
Schedules are evaluated in order. The first matching schedule is used. The last schedule without a match field serves as the default.
admins
Section titled “admins”List of GitHub usernames that have SSH access to the runners launched for this repository. They come in addition to the admins defined at the CloudFormation stack level.
Example
Section titled “Example”admins: - crohr - other-github-userFull example
Section titled “Full example”_extends: .github-private
images: mycustomimage: platform: "linux" arch: "x64" owner: "099720109477" # will take the most recent AMI matching the wildcard pattern name: "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
otherimage: platform: "linux" arch: "x64" ami: "ami-0abcd159cbfafefgh"
runners: cheap: # Useful for workflows that do not require a lot of CPU / RAM. ram: [2, 4, 8] # Burstable instances, valid for both x64 and arm64 family: ["t3", "t4"] image: otherimage ssh: false fast: cpu: 32 disk: large family: ["c7a", "m7a"] spot: false # reference custom image defined above image: mycustomimage preinstall: | echo "doing some stuff before the GitHub Actions runner agent is executed..." echo "For instance, disabling the host's IPv6 if needed" sysctl -w net.ipv6.conf.all.disable_ipv6=1
admins: - crohr - other-github-userUsing the configuration in a GitHub Workflow
Section titled “Using the configuration in a GitHub Workflow”jobs: test: runs-on: runs-on=${{github.run_id}}/runner=2cpu-linux-x64/image=mycustomimagejobs: test: runs-on: runs-on=${{github.run_id}}/runner=2cpu-linux-x64/image=otherimagejobs: test: runs-on: runs-on=${{github.run_id}}/runner=cheapjobs: test: runs-on: runs-on=${{github.run_id}}/runner=fastSharing configuration across repositories
Section titled “Sharing configuration across repositories”RunsOn comes with a feature that allows a local configuration file to inherit from a globally defined configuration file, by using the _extends directive.
The recommendation is to store the global configuration file in the special .github-private repository of your organization, but you can choose any other repository as well (public or private).
Example:
_extends: .github-privaterunners: cheap-arm64: cpu: [1, 2] family: ["t4g"] image: ubuntu22-full-arm64