The Oxide GitHub Actions runner scale set controller provides elastic, self-hosted GitHub Actions runner capacity on Oxide. It runs workflow jobs on ephemeral Oxide instances using a custom image you control without needing to maintain a fleet of static long-lived runners.
The controller creates and manages a GitHub Actions runner scale set and adjusts its capacity in response to demand. It provisions instances with just-in-time runner configurations and removes each instance and boot disk after its runner exits. You can also keep a configurable pool of idle runners to reduce job start latency.
This guide describes how to use the Oxide GitHub Actions runner scale set controller to run CI/CD workflow jobs on Oxide.
Requirements
To follow this guide, you need the following.
API credentials for your Oxide silo. Refer to Authentication for instructions on generating API credentials.
A project within your Oxide silo with a configured VPC and subnet. The controller will provision Oxide instances in this project, VPC, and subnet.
An Oxide image in your project prepared as an ephemeral, single-job GitHub Actions runner image. The controller source code includes a reference Packer configuration to build and upload a compatible image.
A GitHub repository for the controller to register a scale set and run a workflow job.
Generate GitHub credentials
The controller authenticates to GitHub using a personal access token (PAT) to simplify following this guide. In production, you’d configure the controller to authenticate using a GitHub App instead.
Navigate to https://github.com/settings/personal-access-tokens.
Click Generate new token.
Set the following:
Token name:
oxide-gha-runner
Under Repository access, select All repositories.
Under Permissions, click Repositories → Add permissions and set:
Administration: Read and write
Click Generate token.
Save the PAT to a secure location.
Start the controller
Download the latest release of the controller from GitHub.
Create
config.yamlwith the following content.Placeholder Value ${GITHUB_ORG}GitHub organization to register the runner scale set.
${GITHUB_REPO}GitHub repository to register the runner scale set.
${GITHUB_TOKEN}GitHub personal access token (PAT).
${OXIDE_HOST}Oxide silo host.
${OXIDE_TOKEN}Oxide API token.
${OXIDE_PROJECT}Oxide project to create the runners in.
${OXIDE_IMAGE}Image to use for the runners.
${OXIDE_VPC}VPC to create the runners in.
${OXIDE_SUBNET}Subnet to create the runners in.
config.yaml---
log:
level: info
format: json
github:
config_url: https://github.com/${GITHUB_ORG}/${GITHUB_REPO}
auth:
pat:
token: ${GITHUB_TOKEN}
oxide:
host: ${OXIDE_HOST}
token: ${OXIDE_TOKEN}
scale_set:
name: oxide-gha-runner
runner_group: default
labels:
- oxide-gha-runner
min_runners: 1
max_runners: 1
instance:
project: ${OXIDE_PROJECT}
image: ${OXIDE_IMAGE}
cpus: 2
memory_gib: 8
vpc: ${OXIDE_VPC}
subnet: ${OXIDE_SUBNET}Start the controller. Keep the terminal open to view its logs.
oxide-gha-runner-scale-set-controller --config config.yamlNavigate to your Oxide project. In a few moments you’ll see an instance created with a name starting with
gha-runner-.Navigate to
https:/. In a few moments you’ll see a runner with a name matching the created Oxide instance. The runner will show/ github.com/ ${GITHUB_ORG}/ ${GITHUB_REPO}/ settings/ actions/ runners Idlewhen it’s ready and waiting for a workflow job.
Run a workflow job
In your GitHub repository, create a workflow file
.github/.workflows/ oxide-gha-runner.yaml .github/workflows/oxide-gha-runner.yaml---
name: Oxide GitHub Actions
on: workflow_dispatch
jobs:
oxide:
# Matches the scale_set.labels configuration.
runs-on: oxide-gha-runner
steps:
- run: |
echo "Hello from Oxide!"Go to your repository on GitHub, navigate to Actions, select the Oxide GitHub Actions workflow, and click Run workflow.
Navigate back to the terminal running the controller. You’ll see its logs show it tearing down the instance once the workflow job completes.
Clean up
Let’s remove the resources we created in this guide.
Drain the controller
Stop the controller using Ctrl+C.
Open
config.yamland set:scale_set.min_runners→0scale_set.max_runners→0
Start the controller.
oxide-gha-runner-scale-set-controller --config config.yamlThe controller will print a log showing it started draining. It will delete the runners and exit successfully when finished.
Remove the workflow file
In your GitHub repository, remove the workflow file
.github/.
Delete GitHub credentials
Navigate to https://github.com/settings/personal-access-tokens.
Delete the personal access token that was generated earlier.