From 3d30fc023862e393c903833d2683dade9e8a07e4 Mon Sep 17 00:00:00 2001 From: Diogo Moura Date: Sun, 21 Sep 2025 14:25:39 +0100 Subject: [PATCH 1/4] feat: Introduce Amazon Linux 2023 ARM image --- .../github_agent.linux.pkr.hcl | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 images/linux-al2023-arm/github_agent.linux.pkr.hcl diff --git a/images/linux-al2023-arm/github_agent.linux.pkr.hcl b/images/linux-al2023-arm/github_agent.linux.pkr.hcl new file mode 100644 index 0000000000..13d7f5b1af --- /dev/null +++ b/images/linux-al2023-arm/github_agent.linux.pkr.hcl @@ -0,0 +1,204 @@ +packer { + required_plugins { + amazon = { + version = ">= 1.0.0" + source = "github.com/hashicorp/amazon" + } + } +} + +variable "runner_version" { + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null +} + +variable "region" { + description = "The region to build the image in" + type = string + default = "eu-west-1" +} + +variable "security_group_id" { + description = "The ID of the security group Packer will associate with the builder to enable access" + type = string + default = null +} + +variable "subnet_id" { + description = "If using VPC, the ID of the subnet, such as subnet-12345def, where Packer will launch the EC2 instance. This field is required if you are using an non-default VPC" + type = string + default = null +} + +variable "associate_public_ip_address" { + description = "If using a non-default VPC, there is no public IP address assigned to the EC2 instance. If you specified a public subnet, you probably want to set this to true. Otherwise the EC2 instance won't have access to the internet" + type = string + default = null +} + +variable "instance_type" { + description = "The instance type Packer will use for the builder" + type = string + default = "t4g.small" +} + +variable "iam_instance_profile" { + description = "IAM instance profile Packer will use for the builder. An empty string (default) means no profile will be assigned." + type = string + default = "" +} + +variable "root_volume_size_gb" { + type = number + default = 8 +} + +variable "ebs_delete_on_termination" { + description = "Indicates whether the EBS volume is deleted on instance termination." + type = bool + default = true +} + +variable "global_tags" { + description = "Tags to apply to everything" + type = map(string) + default = {} +} + +variable "ami_tags" { + description = "Tags to apply to the AMI" + type = map(string) + default = {} +} + +variable "snapshot_tags" { + description = "Tags to apply to the snapshot" + type = map(string) + default = {} +} + +variable "custom_shell_commands" { + description = "Additional commands to run on the EC2 instance, to customize the instance, like installing packages" + type = list(string) + default = [] +} + +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + +source "amazon-ebs" "githubrunner" { + ami_name = "github-runner-al2023-arm64-${formatdate("YYYYMMDDhhmm", timestamp())}" + instance_type = var.instance_type + iam_instance_profile = var.iam_instance_profile + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip + + source_ami_filter { + filters = { + name = "al2023-ami-2023.*-kernel-6.*-arm64" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["137112412989"] + } + ssh_username = "ec2-user" + tags = merge( + var.global_tags, + var.ami_tags, + { + OS_Version = "al2023" + Release = "Latest" + Base_AMI_Name = "{{ .SourceAMIName }}" + }) + snapshot_tags = merge( + var.global_tags, + var.snapshot_tags, + ) + + + launch_block_device_mappings { + device_name = "/dev/xvda" + volume_size = "${var.root_volume_size_gb}" + volume_type = "gp3" + delete_on_termination = "${var.ebs_delete_on_termination}" + } +} + +build { + name = "githubactions-runner" + sources = [ + "source.amazon-ebs.githubrunner" + ] + provisioner "shell" { + environment_vars = [] + inline = concat([ + "sudo dnf upgrade-minimal -y", + "sudo dnf install -y amazon-cloudwatch-agent jq git docker", + "sudo dnf install -y --allowerasing curl", + "sudo systemctl enable docker.service", + "sudo systemctl enable containerd.service", + "sudo service docker start", + "sudo usermod -a -G docker ec2-user", + ], var.custom_shell_commands) + } + + provisioner "file" { + content = templatefile("../install-runner.sh", { + install_runner = templatefile("../../modules/runners/templates/install-runner.sh", { + ARM_PATCH = "" + S3_LOCATION_RUNNER_DISTRIBUTION = "" + RUNNER_ARCHITECTURE = "arm64" + }) + }) + destination = "/tmp/install-runner.sh" + } + + provisioner "shell" { + environment_vars = [ + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-arm64-${local.runner_version}.tar.gz" + ] + inline = [ + "sudo chmod +x /tmp/install-runner.sh", + "echo ec2-user > /tmp/install-user.txt", + "sudo RUNNER_ARCHITECTURE=arm64 RUNNER_TARBALL_URL=$RUNNER_TARBALL_URL /tmp/install-runner.sh" + ] + } + + provisioner "file" { + content = templatefile("../start-runner.sh", { + start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) + }) + destination = "/tmp/start-runner.sh" + } + + provisioner "shell" { + inline = [ + "sudo mv /tmp/start-runner.sh /var/lib/cloud/scripts/per-boot/start-runner.sh", + "sudo chmod +x /var/lib/cloud/scripts/per-boot/start-runner.sh", + ] + } + + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } +} From aeaca0cba81f44ca059fef8fa4281aa6024bf144 Mon Sep 17 00:00:00 2001 From: Diogo Moura Date: Fri, 26 Sep 2025 11:41:56 +0100 Subject: [PATCH 2/4] Remove unused variable --- modules/runners/templates/install-runner.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/runners/templates/install-runner.sh b/modules/runners/templates/install-runner.sh index 05445eb98b..23fef8ac95 100644 --- a/modules/runners/templates/install-runner.sh +++ b/modules/runners/templates/install-runner.sh @@ -3,7 +3,6 @@ ## install the runner s3_location=${S3_LOCATION_RUNNER_DISTRIBUTION} -architecture=${RUNNER_ARCHITECTURE} if [ -z "$RUNNER_TARBALL_URL" ] && [ -z "$s3_location" ]; then echo "Neither RUNNER_TARBALL_URL or s3_location are set" From dac5853aa3a0ae686e5572c309ac903493c71dd9 Mon Sep 17 00:00:00 2001 From: Diogo Moura Date: Fri, 26 Sep 2025 11:42:35 +0100 Subject: [PATCH 3/4] Parameterize architecture --- .../github_agent.linux.pkr.hcl | 204 ------------------ .../linux-al2023/github_agent.linux.pkr.hcl | 26 ++- 2 files changed, 18 insertions(+), 212 deletions(-) delete mode 100644 images/linux-al2023-arm/github_agent.linux.pkr.hcl diff --git a/images/linux-al2023-arm/github_agent.linux.pkr.hcl b/images/linux-al2023-arm/github_agent.linux.pkr.hcl deleted file mode 100644 index 13d7f5b1af..0000000000 --- a/images/linux-al2023-arm/github_agent.linux.pkr.hcl +++ /dev/null @@ -1,204 +0,0 @@ -packer { - required_plugins { - amazon = { - version = ">= 1.0.0" - source = "github.com/hashicorp/amazon" - } - } -} - -variable "runner_version" { - description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." - default = null -} - -variable "region" { - description = "The region to build the image in" - type = string - default = "eu-west-1" -} - -variable "security_group_id" { - description = "The ID of the security group Packer will associate with the builder to enable access" - type = string - default = null -} - -variable "subnet_id" { - description = "If using VPC, the ID of the subnet, such as subnet-12345def, where Packer will launch the EC2 instance. This field is required if you are using an non-default VPC" - type = string - default = null -} - -variable "associate_public_ip_address" { - description = "If using a non-default VPC, there is no public IP address assigned to the EC2 instance. If you specified a public subnet, you probably want to set this to true. Otherwise the EC2 instance won't have access to the internet" - type = string - default = null -} - -variable "instance_type" { - description = "The instance type Packer will use for the builder" - type = string - default = "t4g.small" -} - -variable "iam_instance_profile" { - description = "IAM instance profile Packer will use for the builder. An empty string (default) means no profile will be assigned." - type = string - default = "" -} - -variable "root_volume_size_gb" { - type = number - default = 8 -} - -variable "ebs_delete_on_termination" { - description = "Indicates whether the EBS volume is deleted on instance termination." - type = bool - default = true -} - -variable "global_tags" { - description = "Tags to apply to everything" - type = map(string) - default = {} -} - -variable "ami_tags" { - description = "Tags to apply to the AMI" - type = map(string) - default = {} -} - -variable "snapshot_tags" { - description = "Tags to apply to the snapshot" - type = map(string) - default = {} -} - -variable "custom_shell_commands" { - description = "Additional commands to run on the EC2 instance, to customize the instance, like installing packages" - type = list(string) - default = [] -} - -variable "temporary_security_group_source_public_ip" { - description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." - type = bool - default = false -} - -data "http" github_runner_release_json { - url = "https://api.github.com/repos/actions/runner/releases/latest" - request_headers = { - Accept = "application/vnd.github+json" - X-GitHub-Api-Version : "2022-11-28" - } -} - -locals { - runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) -} - -source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-al2023-arm64-${formatdate("YYYYMMDDhhmm", timestamp())}" - instance_type = var.instance_type - iam_instance_profile = var.iam_instance_profile - region = var.region - security_group_id = var.security_group_id - subnet_id = var.subnet_id - associate_public_ip_address = var.associate_public_ip_address - temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip - - source_ami_filter { - filters = { - name = "al2023-ami-2023.*-kernel-6.*-arm64" - root-device-type = "ebs" - virtualization-type = "hvm" - } - most_recent = true - owners = ["137112412989"] - } - ssh_username = "ec2-user" - tags = merge( - var.global_tags, - var.ami_tags, - { - OS_Version = "al2023" - Release = "Latest" - Base_AMI_Name = "{{ .SourceAMIName }}" - }) - snapshot_tags = merge( - var.global_tags, - var.snapshot_tags, - ) - - - launch_block_device_mappings { - device_name = "/dev/xvda" - volume_size = "${var.root_volume_size_gb}" - volume_type = "gp3" - delete_on_termination = "${var.ebs_delete_on_termination}" - } -} - -build { - name = "githubactions-runner" - sources = [ - "source.amazon-ebs.githubrunner" - ] - provisioner "shell" { - environment_vars = [] - inline = concat([ - "sudo dnf upgrade-minimal -y", - "sudo dnf install -y amazon-cloudwatch-agent jq git docker", - "sudo dnf install -y --allowerasing curl", - "sudo systemctl enable docker.service", - "sudo systemctl enable containerd.service", - "sudo service docker start", - "sudo usermod -a -G docker ec2-user", - ], var.custom_shell_commands) - } - - provisioner "file" { - content = templatefile("../install-runner.sh", { - install_runner = templatefile("../../modules/runners/templates/install-runner.sh", { - ARM_PATCH = "" - S3_LOCATION_RUNNER_DISTRIBUTION = "" - RUNNER_ARCHITECTURE = "arm64" - }) - }) - destination = "/tmp/install-runner.sh" - } - - provisioner "shell" { - environment_vars = [ - "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-arm64-${local.runner_version}.tar.gz" - ] - inline = [ - "sudo chmod +x /tmp/install-runner.sh", - "echo ec2-user > /tmp/install-user.txt", - "sudo RUNNER_ARCHITECTURE=arm64 RUNNER_TARBALL_URL=$RUNNER_TARBALL_URL /tmp/install-runner.sh" - ] - } - - provisioner "file" { - content = templatefile("../start-runner.sh", { - start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) - }) - destination = "/tmp/start-runner.sh" - } - - provisioner "shell" { - inline = [ - "sudo mv /tmp/start-runner.sh /var/lib/cloud/scripts/per-boot/start-runner.sh", - "sudo chmod +x /var/lib/cloud/scripts/per-boot/start-runner.sh", - ] - } - - post-processor "manifest" { - output = "manifest.json" - strip_path = true - } -} diff --git a/images/linux-al2023/github_agent.linux.pkr.hcl b/images/linux-al2023/github_agent.linux.pkr.hcl index de72a9466f..f3c590486f 100644 --- a/images/linux-al2023/github_agent.linux.pkr.hcl +++ b/images/linux-al2023/github_agent.linux.pkr.hcl @@ -1,7 +1,7 @@ packer { required_plugins { amazon = { - version = ">= 0.0.2" + version = ">= 1.0.0" source = "github.com/hashicorp/amazon" } } @@ -12,6 +12,16 @@ variable "runner_version" { default = null } +variable "architecture" { + description = "The architecture of the runner. Supported values are 'x86-64' and 'arm64'" + type = string + default = "x86_64" + validation { + condition = contains(["arm64", "x86_64"], var.architecture) + error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." + } +} + variable "region" { description = "The region to build the image in" type = string @@ -39,7 +49,7 @@ variable "associate_public_ip_address" { variable "instance_type" { description = "The instance type Packer will use for the builder" type = string - default = "m3.medium" + default = "t4g.small" } variable "iam_instance_profile" { @@ -99,12 +109,13 @@ data "http" github_runner_release_json { locals { runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) + instance_type = coalesce(var.instance_type, var.architecture == "arm64" ? "t4g.small" : "m3.medium") } source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-al2023-x86_64-${formatdate("YYYYMMDDhhmm", timestamp())}" + ami_name = "github-runner-al2023-${var.architecture}-${formatdate("YYYYMMDDhhmm", timestamp())}" instance_type = var.instance_type - iam_instance_profile = var.iam_instance_profile + iam_instance_profile = var.iam_instance_profile region = var.region security_group_id = var.security_group_id subnet_id = var.subnet_id @@ -113,7 +124,7 @@ source "amazon-ebs" "githubrunner" { source_ami_filter { filters = { - name = "al2023-ami-2023.*-kernel-6.*-x86_64" + name = "al2023-ami-2023.*-kernel-6.*-${var.architecture}" root-device-type = "ebs" virtualization-type = "hvm" } @@ -166,7 +177,6 @@ build { install_runner = templatefile("../../modules/runners/templates/install-runner.sh", { ARM_PATCH = "" S3_LOCATION_RUNNER_DISTRIBUTION = "" - RUNNER_ARCHITECTURE = "x64" }) }) destination = "/tmp/install-runner.sh" @@ -174,12 +184,12 @@ build { provisioner "shell" { environment_vars = [ - "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-x64-${local.runner_version}.tar.gz" + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-${var.architecture}-${local.runner_version}.tar.gz" ] inline = [ "sudo chmod +x /tmp/install-runner.sh", "echo ec2-user > /tmp/install-user.txt", - "sudo RUNNER_ARCHITECTURE=x64 RUNNER_TARBALL_URL=$RUNNER_TARBALL_URL /tmp/install-runner.sh" + "sudo RUNNER_TARBALL_URL=$RUNNER_TARBALL_URL /tmp/install-runner.sh" ] } From 6e595ef9b6a1cdc1d4c0dc0eaa3575703beec3c7 Mon Sep 17 00:00:00 2001 From: Diogo Moura Date: Fri, 26 Sep 2025 12:24:05 +0100 Subject: [PATCH 4/4] Align defaults --- images/linux-al2023/github_agent.linux.pkr.hcl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/images/linux-al2023/github_agent.linux.pkr.hcl b/images/linux-al2023/github_agent.linux.pkr.hcl index f3c590486f..929042f06a 100644 --- a/images/linux-al2023/github_agent.linux.pkr.hcl +++ b/images/linux-al2023/github_agent.linux.pkr.hcl @@ -13,12 +13,12 @@ variable "runner_version" { } variable "architecture" { - description = "The architecture of the runner. Supported values are 'x86-64' and 'arm64'" + description = "The architecture of the runner. Supported values are 'x64' and 'arm64'" type = string - default = "x86_64" + default = "x64" validation { - condition = contains(["arm64", "x86_64"], var.architecture) - error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." + condition = contains(["arm64", "x64"], var.architecture) + error_message = "`architecture` value is not valid, valid values are: `arm64` and `x64`." } } @@ -49,7 +49,7 @@ variable "associate_public_ip_address" { variable "instance_type" { description = "The instance type Packer will use for the builder" type = string - default = "t4g.small" + default = null } variable "iam_instance_profile" { @@ -109,12 +109,12 @@ data "http" github_runner_release_json { locals { runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) - instance_type = coalesce(var.instance_type, var.architecture == "arm64" ? "t4g.small" : "m3.medium") + instance_type = coalesce(var.instance_type, var.architecture == "arm64" ? "t4g.medium" : "m3.medium") } source "amazon-ebs" "githubrunner" { ami_name = "github-runner-al2023-${var.architecture}-${formatdate("YYYYMMDDhhmm", timestamp())}" - instance_type = var.instance_type + instance_type = local.instance_type iam_instance_profile = var.iam_instance_profile region = var.region security_group_id = var.security_group_id @@ -124,7 +124,7 @@ source "amazon-ebs" "githubrunner" { source_ami_filter { filters = { - name = "al2023-ami-2023.*-kernel-6.*-${var.architecture}" + name = "al2023-ami-2023.*-kernel-6.*-${var.architecture == "x64" ? "x86_64" : var.architecture}" root-device-type = "ebs" virtualization-type = "hvm" }