Prerequisites
Before Quickstart, we need to sort out the inputs for mode: refresh
in order to initialize everything. Once done, these inputs are used in .github/workflows/refresh.yml
- like so:
Example - .github/workflows/refresh.yml
jobs:
refresh_job:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@main
with:
# IAM User credentials for GH Runner
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
# Github Personal Access Token
github-token: ${{ secrets.GH_PAT }}
# EC2 Machine Image
ami: ami-123
# Profile passed on to the EC2 instance for permissions
iam-instance-profile: your-instance-profile
# Security group assigned to EC2 instances
security-group-ids: sg-123
# Subnets where EC2s are placed
subnet-ids: subnet-123 subnet-456 subnet-789
# AWS region (default: us-east-1)
aws-region: us-east-1
# Injected script, install additional packages here, see Machine Image section below
pre-runner-script: |
echo "hello world"
Here's your checklist:
- GitHub Personal Access Token (PAT)
- Networking: VPC, Subnet and Security Group
- IAM User & Permissions for GitHub Actions Workflow
- IAM Role & Instance Profile for EC2 Instances
- Machine Image: EC2 AMI image
1. GitHub Personal Access Token (PAT)
A GitHub Personal Access Token (PAT) is required for the action to manage self-hosted runners. This will be used for the refresh
mode creates temporary tokens to handles runner registration with GitHub.
- Create the PAT with
repo
scope - Store as a secret named
GH_PAT
. We access this asgithub-token: ${{ secrets.GH_PAT }}
# used here ...
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
github-token: ${{ secrets.GH_PAT }} # <----
2. Networking
For this action to work, we need an available VPC, Subnet and Security group
- VPC: Create a new VPC or use an existing one
- Subnet: Ensure that the subnet can reach the internet (public subnet, or private subnet with a NAT Gateway)
- Security Group: When getting started, I recommend creating a permissive security groups and narrow down from there. If you need more restriction, see github's recommendation
# used here ...
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
security-group-ids: sg-123 # <-----
subnet-ids: subnet-123 subnet-456 subnet-789 # <-----
Recommendation: 1 VPC with a subnet per AWS Region's availability zones
While atleast one subnet is required. I recommend creating and inputting a subnet for each of the availability zones to ensure that for however many instances is required for a workflow, AWS can quickly and cheaply provide them.
Note: Accessibility to DynamoDB
The created instances polls the dynamodb service for various functionalities (safe self-termination, liveliness, etc.). When hardening access, just ensure that dynamodb is still accessible for the instances.
3. IAM User for GitHub Actions Workflow
For the GitHub Actions workflow to interact with your AWS account (to manage EC2 instances, DynamoDB, SQS, Launch Templates, etc.), it needs an IAM identity with appropriate permissions. We will be using aws-actions/configure-aws-credentials
To quickly get started, we will be using an IAM User with credentials stored secrets with names: AWS_ACCESS_KEY_ID
& AWS_SECRET_ACCESS_KEY
. Consider using OIDC for further hardening.
Policy for GitHub Actions Workflow
This policy grants the GitHub Actions workflow the necessary permissions. The iam:PassRole
permission is crucial for allowing the workflow to pass an IAM role to the EC2 instances it creates (the EC2 Instance Profile).
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateFleet",
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:CreateTags",
"ec2:*LaunchTemplate*",
"ec2:Describe*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["iam:PassRole"],
"Resource": "arn:aws:iam::*:role/*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:*Item",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:DescribeTable",
"dynamodb:CreateTable",
"dynamodb:ListTables"
],
"Resource": "arn:aws:dynamodb:*:*:table/*"
},
{
"Effect": "Allow",
"Action": ["sqs:*Queue*", "sqs:*Message"],
"Resource": "arn:aws:sqs:*:*:*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": ["spotfleet.amazonaws.com", "ec2.amazonaws.com"]
}
}
}
]
}
# used here ...
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@main
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # <---
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # <---
aws-region: us-east-1
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
# ...
4. IAM Role & Instance Profile for EC2 Instances
The EC2 instances launched by this action need their own set of permissions to perform tasks (see: instance agent) These permissions are granted via an IAM Role -> attached to the instances through an EC2 Instance Profile.
To quickly get started, use the AWS console to create an IAM Role. When you select “EC2” as the trusted service during role creation, the console automagically generates a matching EC2 Instance Profile (with the same name). Once the role and its instance profile exist, attach the following policies
Policy for EC2 Instance Profile
This policy allows the EC2 instances to interact with DynamoDB and terminate themselves if they carry a specific tag.
# used here...
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
iam-instance-profile: your-instance-profile # <---
The example policies above are provided as a guide - See Advanced Configuration for hardening!
5. Machine Image
Quickstart Recommendation: Runs On Community AMI Images
To get up and running, I recommend using run-on's AWS AMI images. This will get you started quickly as they graciously keep an EC2-compatible machine image up to date with the packages used by the official Github Runner images.
# used here...
- name: Refresh Mode
uses: fleet-actions/ec2-runner-pool-manager@main
with:
mode: refresh
ami: ami-123 # <---
Other Images (Amazon Linux/Ubuntu)
If you want to get started with other machine images, see prescriptions at Advanced Configuration - custom AMIs and pre runner scripts