Skip to content

Latest commit

 

History

History
296 lines (215 loc) · 17.8 KB

README.md

File metadata and controls

296 lines (215 loc) · 17.8 KB

terraform-aws-github-runners

Deploy GitHub Action runners in your AWS Account. Uses AWS CodeBuild to manage ephemeral runners, so you don't have to.

GitHub repo link


Maintenance Test Status Terraform Version pre-commit

Previous version notice

Previously, this module used EC2 spot instances with configurable AutoScaling.

Should you wish to continue to use this older approach, the code has been moved to (terraform-aws-github-runners-ec2)[https://github.com/cloudandthings/terraform-aws-github-runners-ec2].

Features

  • Simple! See the provided examples for a quick-start.
  • Serverless. No EC2 instances that need to be maintained
  • Cost-effective. Only billed for when CodeBuild project is running as projects are billed per build minute.
  • Scalable. By default one runner process and 20GB storage is provided per vCPU per EC2 instance.

A full list of created resources is shown below.

Why?

Deploying self-hosted GitHub runner should be simple. It shouldn't need a long setup process or a lot of infrastructure.

This module additionally does not require public inbound traffic, and can be easily customised if needed.

Known limitations

  1. Additional config needed if using custom ECR image

If a custom ECR image is used then additional install and config is needed when building the Docker image. This is because some of the GitHub uses actions do not work by default.

How it works

Infrastructure diagram

An AWS CodeBuild Project and a webhook is created in a specific GitHub repo. The webhook is used to trigger the build project when a Github Action is triggered. The CodeBuild project run will self-configure as a GitHub runner, and run the job commands in the repo's workflow file.

Steps execute arbitrary commands, defined by your repo workflows.

For example:

  • Perform a linting check.
  • Connect to another AWS Account using an IAM credential and operate on some AWS infrastructure.
  • Anything else...

How to use it

1. Decide on how to authenticate to GitHub

Here we focus on setting up a personal access token to authenticate to GitHub. OAuth is also supported but not implemented / documented here.

GitHub access token

Note that CodeBuild only supports 1 GitHub token to be configured for all CodeBuild projects in the same AWS Account and Region.

Therefore, when using multiple CodeBuild projects, you can configure the token once per region (not once per project).

There are a few approaches that you could take, choose one from the below.

2. Create your GitHub token

Create a GitHub personal access token. Make sure that the fine grained token has these permissions.

2a. Add the token to CodeBuild separately.

You would add the token as documented here This is recommended if you do not want to maintain the token in Terraform.

2b. Provide the token as an input Terraform variable

Note that although the variable is sensitive, the value will still be stored in Terraform state.

2c. Use AWS Parameter Store

Add the token to AWS Systems Manager Parameter Store, and configure this module to read it. The module will add the token to Codebuild for you.

This is recommended if you have only a single project.

Adding your token to Parameter Store (Optional)

Add it to AWS Systems Manager Parameter Store with the SecureString type.

Parameter Store configuration

2. Configure this module

Configure and deploy this module using Terraform. See examples below.

More info

Module Docs

Basic Example

module "github_runner" {
  source = "../../"

  # Required parameters
  ############################
  source_location              = "https://github.com/my-org/my-repo.git"
  github_personal_access_token = "example"

  # Naming for all created resources
  name = "github-runner-codebuild-test"

  vpc_id     = "vpc-0ffaabbcc1122"
  subnet_ids = ["subnet-0123", "subnet-0456"]
}

Advanced Example

locals {
  naming_prefix = "test-github-runner"
  vpc_id        = "vpc-0ffaabbcc1122"
}

# Create a custom security-group to allow SSH to all EC2 instances
resource "aws_security_group" "this" {
  name        = "${local.naming_prefix}-sg"
  description = "GitHub runner ${local.naming_prefix}-sg"

  # tfsec:ignore:aws-ec2-no-public-egress-sgr
  egress {
    description = "egress"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  vpc_id = local.vpc_id
  #checkov:skip=CKV2_AWS_5:The SG is attached by the module.
  #checkov:skip=CKV_AWS_382:Egress to GitHub Actions is required for the runner to work.
}

data "http" "myip" {
  url = "http://ipv4.icanhazip.com"
}

resource "aws_security_group_rule" "ssh_ingress" {
  description       = "Allow SSH ingress to EC2 instance"
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["${chomp(data.http.myip.body)}/32"]
  security_group_id = aws_security_group.this.id
}

module "github_runner" {
  source = "../../"

  # Required parameters
  ############################
  source_location                            = "https://github.com/my-org/my-repo.git"
  github_personal_access_token_ssm_parameter = "example"

  # Naming for all created resources
  name = "github-runner-codebuild-test"

  vpc_id     = "vpc-0ffaabbcc1122"
  subnet_ids = ["subnet-0123", "subnet-0456"]
  # Optional parameters
  ################################

  security_group_ids         = [aws_security_group.this.id]
  use_ecr_image              = true
  cloudwatch_logs_group_name = "/some/log/group"
}

Inputs

Name Description Type Default Required
build_timeout Number of minutes, from 5 to 2160 (36 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. number 5 no
cloudwatch_log_group_retention_in_days Number of days to retain log events number 14 no
cloudwatch_logs_group_name Name of the log group used by the codebuild project. If blank then a default is used. string null no
cloudwatch_logs_stream_name Name of the log stream used by the codebuild project. If blank then a default is used. string null no
create_cloudwatch_log_group Determines whether a log group is created by this module. If not, AWS will automatically create one if logging is enabled bool true no
description Short description of the project. string null no
environment_compute_type Information about the compute resources the build project will use. Valid values: BUILD_GENERAL1_SMALL, BUILD_GENERAL1_MEDIUM, BUILD_GENERAL1_LARGE, BUILD_GENERAL1_2XLARGE, BUILD_LAMBDA_1GB, BUILD_LAMBDA_2GB, BUILD_LAMBDA_4GB, BUILD_LAMBDA_8GB, BUILD_LAMBDA_10GB. BUILD_GENERAL1_SMALL is only valid if type is set to LINUX_CONTAINER. When type is set to LINUX_GPU_CONTAINER, compute_type must be BUILD_GENERAL1_LARGE. When type is set to LINUX_LAMBDA_CONTAINER or ARM_LAMBDA_CONTAINER, compute_type must be BUILD_LAMBDA_XGB string "BUILD_GENERAL1_SMALL" no
environment_image Docker image to use for this build project. Valid values include Docker images provided by CodeBuild (e.g aws/codebuild/amazonlinux2-x86_64-standard:4.0), Docker Hub images (e.g., hashicorp/terraform:latest). If use_ecr_image is set to true, this value will be ignored and the ECR image location will be used. string "aws/codebuild/amazonlinux2-x86_64-standard:5.0" no
environment_type Type of build environment to use for related builds. Valid values: LINUX_CONTAINER, LINUX_GPU_CONTAINER, WINDOWS_CONTAINER (deprecated), WINDOWS_SERVER_2019_CONTAINER, ARM_CONTAINER, LINUX_LAMBDA_CONTAINER, ARM_LAMBDA_CONTAINER string "LINUX_CONTAINER" no
github_personal_access_token The GitHub personal access token to use for accessing the repository string null no
github_personal_access_token_ssm_parameter The GitHub personal access token to use for accessing the repository string null no
iam_role_name Name of the IAM role to be used, if one is not given a role will be created string null no
iam_role_permissions_boundary ARN of the policy that is used to set the permissions boundary for the IAM service role string null no
iam_role_policies Map of IAM role policy ARNs to attach to the IAM role map(string) {} no
kms_key_id The AWS KMS key to be used string null no
name Created resources will be named with this. string n/a yes
s3_logs_bucket_name Name of the S3 bucket to store logs in. If null then logging to S3 will be disabled. string null no
s3_logs_bucket_prefix Prefix to use for the logs in the S3 bucket string "" no
security_group_ids The list of Security Group IDs for AWS Codebuild to launch ephemeral EC2 instances in. list(string) [] no
source_location Your source code repo location, for example https://github.com/my/repo.git string n/a yes
subnet_ids The list of Subnet IDs for AWS Codebuild to launch ephemeral EC2 instances in. list(string) [] no
use_ecr_image Determines whether the build image will be pulled from ECR, if set to true an ECR repository will be created and an image needs to be pushed to it before running the build project string false no
vpc_id The VPC ID for AWS Codebuild to launch ephemeral instances in. string null no

Modules

No modules.


Outputs

Name Description
codebuild_project Name and ARN of codebuild project, to be used when running GitHub Actions
codebuild_role Name and ARN of codebuild role, to be used when running GitHub Actions
ecr_repository Name and ARN of ECR repository, to be used when to push custom docker images for the codebuiild project

Providers

Name Version
aws ~> 5

Requirements

Name Version
terraform >= 0.14.0
aws ~> 5
http ~> 3.0
null ~> 3.2

Resources

Name Type
aws_cloudwatch_log_group.codebuild resource
aws_codebuild_project.this resource
aws_codebuild_source_credential.ssm resource
aws_codebuild_source_credential.string resource
aws_codebuild_webhook.this resource
aws_ecr_lifecycle_policy.policy resource
aws_ecr_repository.this resource
aws_iam_role.this resource
aws_iam_role_policy.cloudwatch_required resource
aws_iam_role_policy.ecr_required resource
aws_iam_role_policy.networking_required resource
aws_iam_role_policy.s3_required resource
aws_iam_role_policy_attachment.additional resource
aws_security_group.codebuild resource
aws_vpc_security_group_egress_rule.codebuild resource
aws_vpc_security_group_ingress_rule.codebuild resource
aws_caller_identity.current data source
aws_cloudwatch_log_group.codebuild data source
aws_iam_policy_document.assume_role data source
aws_iam_policy_document.cloudwatch_required data source
aws_iam_policy_document.ecr_required data source
aws_iam_policy_document.networking_required data source
aws_iam_policy_document.s3_required data source
aws_region.current data source
aws_ssm_parameter.github_personal_access_token data source

<!-- END_TF_DOCS -->