Alternatives to GitHub-hosted runners

Published on October 24, 2024 | Written by Andreas

Are you seeking an alternative to GitHub-hosted runners? Learn about ec2-github-runner, terraform-aws-github-runner, and HyperEnv to self-host runners with the help of EC2 instances. All three solutions run completely in your AWS account, which gives you full control.

Own Your Dependencies: Customizing GitHub Actions with Container Images

Why should you consider an alternative to GitHub-hosted runners?

There are a bunch of reasons to consider an alternative to GitHub-hosted runners:

  • Reducing costs
  • Utilizing runners with more CPU and memory
  • Increasing the disk space
  • Accessing private networks (e.g., AWS VPC)
  • Customizing the runner by pre-installing software
  • Speeding up GitHub Actions
  • Support for GitHub Enterprise Server

ec2-github-runner: GitHub action to start and stop an EC2 instance

The idea behind ec2-github-runner is simple: provide a GitHub action to launch and terminate EC2 instances.

The following snippet shows a GitHub workflow using the ec2-github-runner action to launch and terminate an EC2 instance.

  1. The GitHub workflow starts.
  2. The start-ec2-runner job launches an EC2 instance.
  3. The EC2 instance registers itself as a self-hosted GitHub runner
  4. The build job runs on the EC2 instance.
  5. The stop-ec2-runner job terminates the EC2 instance.
name: ec2-github-runner-example
on: push
jobs:
  start-ec2-runner:
    name: Start EC2 runner
    runs-on: ubuntu-latest # the job runs on GitHub-hosted runners
    outputs:
      label: ${{ steps.start-ec2-runner.outputs.label }}
      ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }}
    steps:
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: eu-west-1
    - name: Start EC2 runner
      id: start-ec2-runner
      uses: machulav/ec2-github-runner@v2
      with:
        mode: start
        github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
        ec2-image-id: ami-0a2d3c18efb0a2eb0
        ec2-instance-type: m5.large
        subnet-id: subnet-0463cb19720d02c7d
        security-group-id: sg-068a1780a03660482
  build:
    name: Build
    needs: start-ec2-runner # wait for the step to start the EC2 instance
    runs-on: ${{ needs.start-ec2-runner.outputs.label }} # refers to the label used to register the runner
    steps:
    - name: Build
      run: ./build.sh
  stop-ec2-runner:
    name: Stop EC2 runner
    needs:
    - start-ec2-runner # access outputs
    - build # wait for the build job to finish
    runs-on: ubuntu-latest
    if: ${{ always() }} # always stop the EC2 runner, even if the previous job failed
    steps:
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: eu-west-1
    - name: Stop EC2 runner
      uses: machulav/ec2-github-runner@v2
      with:
        mode: stop
        github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
        label: ${{ needs.start-ec2-runner.outputs.label }}
        ec2-instance-id: ${{ needs.start-ec2-runner.outputs.ec2-instance-id }}

The solution requires you to add the following secrets to the GitHub repository.

  • Static AWS credentials (IAM user): AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
  • Personal access token with access to repo scope: GH_PERSONAL_ACCESS_TOKEN

Pros

  • Simple and easy-to-understand solution.
  • Scalable as it launches an EC2 for every workflow/job.
  • Free as in beer. (MIT License)

Cons

  • Does not come with a ready to use AMI. Requires an AMI with Docker pre-installed or the use of pre-runner-script to install Docker on every launch.
  • Manual setup required: security group, VPC + subnet, GitHub personal access token, …
  • Requires static credentials (IAM user) which AWS does not recommend.
  • Uses GitHub-hosted runners to start and stop EC2 instance.

terraform-aws-github-runner: Terraform module to deploy self-hosted runner on AWS

Philips maintains a lively open-source project with terraform-aws-github-runner. As the name implies, the Terraform module provides self-hosted and scalable runners for GitHub Actions.

The architecture consists of the following building blocks:

  • API Gateway
  • Lambda
  • SQS
  • Event Bridge
  • Auto Scaling Group
  • EC2
  • VPC

Overall, the architecture (see diagram) is quite complex.

Here is a summary on how to get started with terraform-aws-github-runner.

  1. Set up a private GitHub app.
  2. Download or build code for Lambda.
  3. Setup Terraform module.
module "github-runner" {
  source  = "philips-labs/github-runner/aws"
  version = "v5.17.3"

  aws_region = "eu-west-1"
  vpc_id     = "vpc-001efbd83d4f4d8fd"
  subnet_ids = ["subnet-0463cb19720d02c7d", "subnet-0f6208cd58b6452b8"]

  prefix = "ghr"

  github_app = {
    key_base64     = "..."
    id             = "1"
    webhook_secret = "..."
  }

  webhook_lambda_zip                = "lambdas-download/webhook.zip"
  runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip"
  runners_lambda_zip                = "lambdas-download/runners.zip"
  enable_organization_runners = true
}
  1. Configure GitHub webhook.
  2. Install the GitHub app.

The terraform-aws-github-runner solution supports re-using runners for multiple jobs as well as ephemeral runners. Optionally, an auto-scaling group can be used to provide a pool of runners to reduce latency when starting a job.

Pros

  • Active and well-maintained open-source project.
  • Optional pool with pre-warmed runners to reduce latency for starting a job.

Cons

  • Complicated installation process which requires to consult the documentation a lot.
  • Complex architecture and Terraform code, requires advanced Terraform and AWS skills.

HyperEnv: Deploy self-hosted GitHub runners on AWS with ease

Deploy self-hosted GitHub runners on AWS with ease by using HyperEnv in three simple steps by clicking through Amazon’s and GitHub’s web interface.

  1. Subscribe to HyperEnv via AWS Marketplace
  2. Create a CloudFormation stack to deploy HyperEnv
  3. Create a private GitHub app for your GitHub organization

HyperEnv runs 100% in your AWS account.

Here is how HyperEnv works after the installation:

  1. GitHub jobs starts and waits for runner.
  2. GitHub sends webhook event to HyperEnv.
  3. HyperEnv launches an EC2 instance which automatically starts and registers a GitHub runner.
  4. GitHub runner executes job.
  5. EC2 instance terminates.

HyperEnv provides an AMI which comes with the same tools pre-installed as GitHub-hosted runners (ubuntu-latest).

Try HyperEnv today!

Pros

  • Easy to install: from start to finish in 15 minutes.
  • Drop-in replacement for GitHub-hosted runners (compatible with ubuntu-latest).
  • Support by AWS and GitHub experts helping you to get started and solve problems.

Cons

  • Costs $0.002 per vCPU and build minute on top of consumed AWS infrastructure resources (see cost calculator).