Skip to content

Building a custom AMI with Packer

RunsOn provides base images (AMIs) for your workflows, which are regularly updated.

In some cases though, you might want to generate a new AMI from one of those base images, and use it in your workflows.

This can be useful if you want to:

  • prepopulate the AMI with your own software, docker images, data, etc.
  • fulfill advanced compliancy requirements, with a stable image that you control.

An easy way to do this is to regularly rebuild your own AMI from the base images with Packer.

Manifest file

In this example we will generate a new AMI for arm64.

packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1"
}
}
}
variable "subnet_id" {
type = string
}
variable "region" {
type = string
}
variable "ami_prefix" {
type = string
}
data "amazon-ami" "runs-on-ami" {
filters = {
name = "runs-on-v2.2-ubuntu22-full-arm64-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["135269210855"]
region = "${var.region}"
}
source "amazon-ebs" "build-ebs" {
ami_name = "${var.ami_prefix}-runs-on-${formatdate("YYYY-MM-DD-hhmmss", timestamp())}"
instance_type = "t4g.small"
region = "${var.region}"
source_ami = "${data.amazon-ami.runs-on-ami.id}"
ssh_username = "ubuntu"
subnet_id = "${var.subnet_id}"
user_data_file = "./scripts/user_data.sh"
}
build {
sources = ["source.amazon-ebs.build-ebs"]
provisioner "shell" {
script = "./scripts/provision.sh"
}
}

User data file

A user-data is required to start the SSH daemon, otherwise Packer can’t connect to the instance to perform the provisioning.

In the example this would be a file in scripts/user_data.sh:

#!/bin/bash
systemctl start ssh

Provisioning file

The provisioning file is where you put your scripts to install software, run commands, etc.

In the example this would be a file in scripts/provision.sh:

#!/bin/bash
set -e
apt-get update
apt-get install -y software1 software2

Building the image

Initialize Packer:

Terminal window
packer init custom-ami-arm64.pkr.hcl

Then build the image:

Terminal window
packer build -var "ami_prefix=MY_COMPANY" -var "subnet_id=your-subnet-id" -var "region=us-east-1" custom-ami-arm64.pkr.hcl

After some time you should get a new AMI registered into your AWS account, and you can start using it by referencing the AMI ID or name in your workflows.

See the documentation on custom images for more details.