Skip to content

terraform-aws-arc-github-runner

Module: sourcefuse/arc-github-runner/aws

Registry: https://registry.terraform.io/modules/sourcefuse/arc-github-runner/aws

Category: DevOps / CI/CD

Source: https://github.com/sourcefuse/terraform-aws-arc-github-runner

Latest Release Last Updated Terraform GitHub Actions

Quality gate

Tip

🤖 New: Use this module with AI assistants via the ARC IaC MCP Server — search, scaffold, and security-scan ARC modules from natural language. Quick setup ↓

Overview

Deploys a self-hosted GitHub Actions runner on an EC2 instance with auto-registration, SSM access, and configurable labels.

What It Does

  • EC2-based self-hosted GitHub Actions runner
  • Automatic runner registration with GitHub token
  • Configurable runner labels for job targeting
  • SSM Session Manager access (no SSH required)
  • IAM instance profile with configurable policies
  • VPC and security group configuration

This module utilizes different local-exec provisioners to execute scripts for obtaining the needed GitHub Runner token and remove the runner from the organization when the resources are destroyed. See Pre-Requisites for information on the needed permissions these scripts will require.

Runners on Amazon EKS

Set eks_runner_config.create = true to run autoscaling, ephemeral runners on an existing EKS cluster. Set create_ec2_runner = false if you do not also want the EC2 runner. The root module then deploys the official Actions Runner Controller runner scale sets with Helm, through the modules/eks-runner submodule. It supports multiple scale sets, Pod Identity or IRSA, and GitHub App auth. See example/eks-runner.

module "github_runner" {
  source  = "sourcefuse/arc-github-runner/aws"
  # version = "x.y.z"

  namespace         = "arc"
  environment       = "dev"
  region            = "us-east-1"
  create_ec2_runner = false

  github_token = data.aws_ssm_parameter.github_token.value # or github_app_private_key

  eks_runner_config = {
    create             = true
    cluster_name       = "my-eks-cluster"
    github_config_url  = "https://github.com/my-org"
    github_auth_method = "pat"
    runner_scale_sets = {
      default = { min_runners = 1, max_runners = 10 }
    }
  }
}

The calling configuration must configure the helm and kubernetes providers for the cluster. EC2-only inputs (vpc_id, subnet_id, ...) are not needed in this mode.

Pre-Requisites

You will need to have a GitHub Personal Access Token (PAT) with admin:org permissions in order to manage GitHub runners for the Organization. If you do not have sufficient permissions to GitHub, the runner will not register.

Once you've obtained a PAT, you will need to set it so Terraform can access it. The recommended approach to this is to save it in Systems Manager Parameter Store with the Parameter name of: /<namespace>/<environment>/github/token You can reference this parameter via a data lookup:

1
2
3
data "aws_ssm_parameter" "github_token" {
  name = "/${var.namespace}/${var.environment}/github/token"
}

Usage

⚠️ At this time, this module only supports Debian / Ubuntu AMIs. When choosing an AMI, please be sure to select either Ubuntu or Debian.

To see a full EC2 example, check out the EC2 runner example.
For EKS runner scale sets, see the EKS runner example.

Quickstart

module "runner" {
  source  = "sourcefuse/arc-github-runner/aws"
  version = "0.2.6"
  namespace     = var.namespace
  environment   = var.environment
  region        = var.region
  subnet_id     = local.private_subnet_ids[0]
  vpc_id        = data.aws_vpc.this.id
  instance_type = "t2.micro"
  github_token  = data.aws_ssm_parameter.github_token.value
  runner_labels = "example,${var.namespace},${var.environment}"

  tags = module.tags.tags
}

Required Inputs

Name Type Description
namespace string Namespace prefix
environment string Deployment environment
subnet_id string Subnet ID for the runner EC2 instance
vpc_id string VPC ID
github_token string GitHub PAT or registration token
runner_labels string Comma-separated runner labels
## Key Outputs
Name Description
instance_id EC2 instance ID of the runner
instance_private_ip Private IP of the runner
## Full Variable & Output Reference

The complete inputs/outputs reference is auto-generated below.

Requirements

Name Version
terraform >= 1.5.0, < 2.0.0
aws >= 5.40, < 6.0
helm >= 2.12, < 4.0
kubernetes >= 2.20, < 4.0
null >= 3.0

Providers

Name Version
aws 5.100.0
null 3.3.2

Modules

Name Source Version
eks_runner ./modules/eks-runner n/a
runner sourcefuse/arc-ec2/aws 0.0.5

Resources

Name Type
aws_ssm_association.dependencies resource
aws_ssm_association.runner_install resource
aws_ssm_document.dependencies resource
aws_ssm_document.runner_install resource
null_resource.cleanup resource
null_resource.prepare resource
aws_caller_identity.this data source

Inputs

Name Description Type Default Required
ami AMI information for the EC2 instance
object({
id = string
owner_id = string
})
{
"id": "ami-04505e74c0741db8d",
"owner_id": "099720109477"
}
no
associate_public_ip_address Associate a public IP address with the instance bool false no
create_ec2_runner Whether to create the EC2 (SSM managed) runner. Set to false when only EKS runners are needed (eks_runner_config.create = true). bool true no
ec2_runner_iam_role_policy_arns IAM role policies to attach to the Runner instance list(string)
[
"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
]
no
eks_runner_config EKS runner configuration. Set create = true to deploy autoscaling, ephemeral
runner scale sets on an existing EKS cluster (official Actions Runner
Controller charts). Attributes map 1:1 to the inputs of
modules/eks-runner, where defaults, validation and
full descriptions live. Unset attributes use the submodule defaults.
Required when create = true: cluster_name, github_config_url.

Credentials are passed separately as sensitive inputs: github_token (PAT)
or github_app_private_key (GitHub App).

Example:
eks_runner_config = {
create = true
cluster_name = "my-eks-cluster"
github_config_url = "https://github.com/my-org"
github_auth_method = "pat"
runner_scale_sets = {
default = { min_runners = 1, max_runners = 10 }
}
}
object({
create = optional(bool, false)
cluster_name = optional(string)
github_config_url = optional(string)
oidc_provider_arn = optional(string)
name_prefix = optional(string)

k8s_namespace = optional(string)
create_k8s_namespace = optional(bool)
k8s_namespace_labels = optional(map(string))
controller_namespace = optional(string)
create_controller_namespace = optional(bool)

install_controller = optional(bool)
controller_service_account = optional(object({
name = string
namespace = string
}))
chart_oci_registry = optional(string)
chart_version = optional(string)
controller_release_name = optional(string)
controller_values = optional(list(string))
helm_timeout = optional(number)
helm_max_history = optional(number)

runner_scale_sets = optional(any)

existing_github_config_secret_name = optional(string)
github_auth_method = optional(string)
github_app_id = optional(string)
github_app_installation_id = optional(string)

iam_auth_type = optional(string)
iam_role_path = optional(string)
iam_role_permissions_boundary = optional(string)

install_ebs_csi_driver = optional(bool)
ebs_csi_addon_version = optional(string)
ebs_csi_kms_key_arn = optional(string)
create_storage_class = optional(bool)
storage_class_name = optional(string)
storage_class_is_default = optional(bool)
storage_class_provisioner = optional(string)
storage_class_volume_type = optional(string)
})
{
"create": false
}
no
environment Name of the environment, i.e. dev, stage, prod string n/a yes
github_app_private_key GitHub App private key (PEM). Used by the EKS runner when eks_runner_config.github_auth_method is "github_app". string null no
github_owner GitHub Owner the runner belongs to. If you are adding a repo, the format will be owner/repo string "sourcefuse" no
github_token GitHub Personal Access Token.
- EC2 runner (create_ec2_runner): required, with admin:org scope. Used to obtain a runner registration token, see
Create a registration token for an organization.
- EKS runner (eks_runner_config.create): used when eks_runner_config.github_auth_method is "pat".
string null no
instance_type The instance type for the EC2 instance. Default is t3a.medium. string "t3a.medium" no
monitoring_enabled Launched EC2 instance will have detailed monitoring enabled bool true no
namespace Namespace of the project, i.e. refarch string n/a yes
region AWS region string n/a yes
repos_or_orgs Whether the API will register / deregister the runner in repos or orgs. Options are orgs and repos string "orgs" no
root_block_device_encrypted Whether to encrypt the root block device bool true no
root_block_device_kms_key_id KMS key ID used to encrypt EBS volume. When specifying root_block_device_kms_key_id, root_block_device_encrypted needs to be set to true string null no
root_volume_size Size of the root volume in gigabytes string "80" no
root_volume_type Type of root volume. Can be standard, gp2, gp3, io1 or io2 string "gp2" no
runner_labels Labels to assign the GitHub Runner. If no values are given, the default labels will be:
- self-hosted
- Base OS, i.e. Linux
- Architecture, i.e. X64
These labels cannot be overridden.
Separate labels via comma, i.e. dev,docker,another_label
string "" no
runner_name Name to assign the GitHub Runner. If no value is given, it will use the ec2 instance name. string null no
runner_user OS user that owns and runs the runner systemd service. Created if it does not exist. string "ubuntu" no
runner_version Version of the official GitHub Actions runner (github.com/actions/runner) to
install on the host. Pin at or above GitHub's current minimum so the runner
is never forced into a self-update. See the releases page for the latest tag.
string "2.336.0" no
subnet_id Subnet ID for the EC2 instance to be assigned to. Required when create_ec2_runner is true. string null no
tags Default tags to apply to every resource map(string) {} no
vpc_id VPC ID for EC2 instance to reside in. Required when create_ec2_runner is true. string null no

Outputs

Name Description
ec2_runner_instance_id Instance ID of the EC2 Runner
ec2_runner_instance_name Instance Name of the EC2 Runner
ec2_runner_role Instance role name (created by arc-ec2 as -role)
ec2_runner_role_arn Instance role ARN
eks_controller_namespace Kubernetes namespace of the Actions Runner Controller.
eks_ebs_csi_role_arn IAM role ARN of the EBS CSI driver (null if not installed).
eks_github_config_secret_name Kubernetes secret holding the GitHub credentials of the EKS runners.
eks_runner_namespace Kubernetes namespace of the EKS runner scale sets.
eks_runner_scale_sets Deployed EKS runner scale sets: name (use in runs-on:), Helm release, runner service account and IAM role ARN.
eks_storage_class_name StorageClass created for runner work volumes (null if not created).

Development

Prerequisites

Configurations

  • Configure pre-commit hooks
    pre-commit install
    

Git commits

while Contributing or doing git commit please specify the breaking change in your commit message whether its major,minor or patch

For Example

git commit -m "your commit message #major"
By specifying this , it will bump the version and if you dont specify this in your commit message then by default it will consider patch and will bump that accordingly

Tests

  • Tests are available in test directory
  • Configure the dependencies
    1
    2
    3
    cd test/
    go mod init github.com/sourcefuse/terraform-aws-refarch-github-runner
    go get github.com/gruntwork-io/terratest/modules/terraform
    
  • Now execute the test
    go test -timeout  30m
    

AI Assistant Integration (ARC IaC MCP)

The ARC IaC MCP Server is a hosted Model Context Protocol service that lets AI assistants browse, search, scaffold, compare, and security-scan any of the SourceFuse ARC Terraform modules — directly from natural language.

What you can do with it:

  • Discover — search and filter modules by keyword or AWS resource type.
  • Understand — get inputs, outputs, and resources for any module without leaving your editor.
  • Scaffold — generate production-ready, multi-file Terraform with cross-module wiring already done.
  • Secure — scan generated or existing HCL for misconfigurations before it hits a PR.
  • Compare — diff modules side-by-side to make informed architectural decisions.

Setup (one minute)

The MCP endpoint is https://arc-iac-mcp.sourcef.us/mcp. Pick your client:

Claude Code CLI:

claude mcp add arc-iac --transport http https://arc-iac-mcp.sourcef.us/mcp

Claude Desktop — edit ~/Library/Application Support/Claude/claude_desktop_config.json:

1
2
3
4
5
6
7
{
  "mcpServers": {
    "arc-iac": {
      "url": "https://arc-iac-mcp.sourcef.us/mcp"
    }
  }
}

Cursor / Windsurf / Kiro — add the same block to .cursor/mcp.json (or the equivalent for your client).

Example prompts to try

  • "List all ARC modules sorted by downloads"
  • "What inputs does arc-ecs require?"
  • "Scaffold a production-ready arc-db Aurora setup with Secrets Manager"
  • "Compare arc-eks and arc-ecs for running 10 microservices"
  • "Scan this Terraform before I raise a PR: <paste HCL>"

See the ARC IaC MCP repo for the full tool reference, troubleshooting tips, and local-development instructions.

Contributing

See CONTRIBUTING.md for commit conventions and development setup.

Authors

This project is authored by: - SourceFuse ARC Team