Skip to content

rstuhlmuller/terraform-aws-ecs-github-runners

Repository files navigation

AWS ECS Self-Hosted Github Runners Module

Terraform module which deploys autoscaling ECS taks in an AWS ECS cluster.

Description

This repository contains infrastructure as code (IaC) for deploying GitHub Actions self-hosted runners on AWS ECS.

It creates the following resources:

  • ECS cluster - Cluster to host the GitHub runner containers
  • ECR repository - Stores the custom GitHub runner container image
  • Dockerfile and scripts - Defines and builds the GitHub runner Docker image, pushes it to ECR
  • Task definition - Defines the GitHub runner container to deploy
  • ECS services - Runs the task definition as a service to maintain runner instances
  • IAM roles and policies - Grants permissions for ECS agent and tasks
  • Secrets Manager secret - Stores github token (can be overwritten)

The runners register themselves to a specified GitHub repository or organization automatically on boot. The number of runners can be adjusted by changing the desired count of the ECS service.

This enables GitHub Actions workloads to scale quickly by adding/removing containers without managing servers directly. Runners auto-update and register themselves, providing a hands-off GitHub runner management system.

The infrastructure is defined as code with HashiCorp Terraform and can be easily extended to other environments. Custom actions and parameters can be configured by modifying the included templates and variables.

Usage

module "aws_ecs_github_runner" {
  source = "git::https://github.com/rstuhlmuller/aws-ecs-github-runners.git?ref=main"

  cluster_name       = "Self-Hosted-Github-Runners"
  security_group_ids = ["<sg_1>"]
  subnet_ids = [
    "<subnet_1>",
    "<subnet_2>"
  ]

  runner_token = "<github_token with permissions to generate runner>"

  runners = {
    runner_1 = {
      org        = "My_Org"
      labels     = "aws,ecs,private"
    }
    runner_2 = {
      org        = "My_Org"
      labels     = "aws,ecs"
    }
  }

  providers = {
    aws = aws
  }
}

Requirements

Name Version
terraform ~> 1.5
aws ~> 5.29
null ~> 3.2

Providers

Name Version
aws ~> 5.29
null ~> 3.2

Modules

No modules.

Resources

Name Type
aws_appautoscaling_policy.scale_down_policy resource
aws_appautoscaling_policy.scale_up_policy resource
aws_appautoscaling_target.scale_target resource
aws_cloudwatch_metric_alarm.cpu_high resource
aws_cloudwatch_metric_alarm.cpu_low resource
aws_ecr_repository.runner_image resource
aws_ecs_cluster.github_runner_cluster resource
aws_ecs_service.runner resource
aws_ecs_task_definition.runner resource
aws_iam_role.ecs_task_execution_role resource
aws_secretsmanager_secret.github_token resource
aws_secretsmanager_secret_version.github_token resource
null_resource.push_ecr resource
aws_caller_identity.current data source
aws_region.current data source

Inputs

Name Description Type Default Required
security_group_ids n/a list(string) n/a yes
subnet_ids n/a list(string) n/a yes
cluster_name n/a string "Self-Hosted-Github-Runners" no
default_runner_config n/a
object({
org = string
labels = optional(string)
runner_prefix = optional(string)
runner_group = optional(string)
cpu = optional(number)
memory = optional(number)
scale_target_min_capacity = optional(number)
scale_target_max_capacity = optional(number)
min_cpu_period = optional(number)
max_cpu_period = optional(number)
max_cpu_threshold = optional(number)
min_cpu_threshold = optional(number)
max_cpu_evaluation_period = optional(number)
min_cpu_evaluation_period = optional(number)
})
{
"cpu": 1,
"labels": null,
"max_cpu_evaluation_period": 3,
"max_cpu_period": 120,
"max_cpu_threshold": 80,
"memory": 3,
"min_cpu_evaluation_period": 3,
"min_cpu_period": 10,
"min_cpu_threshold": 10,
"org": "",
"runner_group": null,
"runner_prefix": "aws-ecs-github-runner",
"scale_target_max_capacity": 10,
"scale_target_min_capacity": 1
}
no
ecs_task_execution_role_name n/a string "aws-ecs-github-runner-task-execution-role" no
force_image_rebuild n/a bool false no
runner_token n/a string "" no
runners n/a any {} no
secret_arn_override n/a string null no
secret_name n/a string "github-token" no
tags n/a map(string) {} no

Outputs

No outputs.

Authors

Module is maintained by Rodman Stuhlmuller

License

MIT Licensed. See LICENSE for full details.