Build Custom AMIs

Using Packer to Build Custom AMIs in Amazon



As you probably already know, there are numerous AMIs available for your use within the Amazon EC2 environment. However, you may find that these are missing some of the software with specific configurations you require. If like me you prefer to use something like Puppet, Chef or Ansible to deploy config changes and have prebuilt OS templates with the software you require to keep things efficient, then you’ll probably want to look at building your own AMIs.

That’s what I’ll explain how to do in this post.


  • Review prerequisites
  • Write a JSON file to be used with Packer
  • Create a bash script to install software required
  • Run Packer to create our AMI

Review prerequisites

In order to utilise Packer with Amazon, you’ll need to obtain your AWS Access Key and AWS Secret Key. This can be created within the IAM section of your Amazon account.

In addition to the above, you’ll also need to pick an existing AMI within Amazon to use as your base image to change. Please make sure you find an AMI within the Amazon Marketplace and that you click Accept Software Terms, otherwise you won’t be able to utilise the AMI, and Packer will exit with an error.


For the purposes of this article, I have chosen an Ubuntu AMI.

Write a JSON file to be used with Packer

The JSON syntax used in a Packer file to build a new AMI is rather self-explanatory and simple to understand.


 "variables": {
   "aws_access_key": "xxxxxxxxxx",
   "aws_secret_key": "xxxxxxxxxx"

 "builders": [{
   "type": "amazon-ebs",
   "communicator": "ssh",
   "ssh_pty": "true",
   "access_key”: "{{user `aws_access_key`}}",
   "secret_key”: "{{user `aws_secret_key`}}",
   "region": "eu-west-1",
   "source_ami": "ami-be3559cd",
   "instance_type": "t2.micro",
   "ssh_username": "ubuntu",
   "ami_name": "puppet {{timestamp}}"

 "provisioners": [{
   "type": "shell",
   "script": "provision/"


In the above snippet, we’re specifying the AWS environment access credentials along with the various settings for our AWS environment, such as region, source AMI, and instance type. Here we also have the ability to name the AMI we’re creating.

Create a bash script to install the software required

Now that we have our provisioning script, we need to write a simple bash script which will go ahead and install the relevant software in our new AMI that Packer is creating. For the purposes of this article, we will create our script and ask it to install apache and htop. We’ll then place it in a folder called, ‘provision’ relative to our working directory. And likewise as above, the file will be named ‘’.


sleep 30
sudo apt-get update -y
sudo apt-get install apache2 htop -y

In the above example, we’re simply installing Puppet to use later. You could also choose at this point to make it connect to your Puppet master to pull config, but that is outside of the scope of this article.

Run Packer to create our AMI

Now that we have our JSON configuration file and bash provisioning script ready to go, we can run Packer to build our new AMI by executing packer build test.json.

Once you’ve executed this, assuming your credentials are correct, you’ll see something similar to the following:

amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name…
==> amazon-ebs: Inspecting the source AMI (ami-be3559cd)…
==> amazon-ebs: Creating temporary keypair: packer_5817da93-2e75-9d71-5797-25444de2b68b
==> amazon-ebs: Creating temporary security group for this instance…
==> amazon-ebs: Authorizing access to port 22 the temporary security group…
==> amazon-ebs: Launching a source AWS instance…
amazon-ebs: Instance ID: i-76cedce1
==> amazon-ebs: Waiting for instance (i-76cedce1) to become ready…
==> amazon-ebs: Waiting for SSH to become available…
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Provisioning with shell script: provision/

Then you’ll see the commands being run inside the instance as part of the provisioning script, along with their output.

At the end, you’ll see something similar to the following, assuming all went to plan:

==> amazon-ebs: Stopping the source instance…
==> amazon-ebs: Waiting for the instance to stop…
==> amazon-ebs: Creating the AMI: puppet 1477958291
amazon-ebs: AMI: ami-7ba9e308
==> amazon-ebs: Waiting for AMI to become ready…
==> amazon-ebs: Terminating the source AWS instance…
==> amazon-ebs: Cleaning up any extra volumes…
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Deleting temporary security group…
Build ‘amazon-ebs’ finished.
==> Builds finished. The artifacts of successful builds are:
–>; amazon-ebs: AMIs were created:
eu-west-1: ami-7ba9e308

As you can see in the above output, we have a new AMI! It really is that simple.


Packer is an excellent piece of software which really helps to simplify deployments in both small and large virtualised/containerized environments. It can be used with many other virtualisation platforms, including but not limited to: Digital Ocean, Docker, Openstack and VMware. A full list is included in the resources section below.


Keith Rogers is an IT professional with over 10 years’ experience in modern development practices. Currently he works for a broadcasting organization in the DevOps space with a focus on automation. Keith is a regular contributor at Fixate IO.


Leave a Comment

Your email address will not be published. Required fields are marked *

Skip to toolbar