Mar 30, 2022

Let’s build a WordPress & Kernel updated AMI with Packer

First, let’s start with What is an AMI?

An Amazon Machine Image (AMI) is a master image for the creation of virtual servers in an AWS environment. The machine images are like templates that are configured with an operating system and other software, which determines the user’s operating system. AMI types are categorized according to region, operating system, system architecture (32- or 64-bit), launch permissions and whether they are backed by Amazon EBS or backed by the instance store. AMIs provide the information required to launch an Amazon EC2 instance, which is a virtual server in the AWS Cloud. 

Each AMI includes the following:

  • A template for the instance’s root device volume
  • Set up permissions that control which Amazon Web Services (AWS) accounts can use the machine images to spin up an instance
  • The block devices that specify the root device volume to attach to the EC2 instance once it’s launched

How to build AMI?

There are various tools available for building the golden AMIs and some of the most used ones are

  • Hashicorp’s Packer
  • AWS Image Builder

We will use Hashicorp’s Packer to create our Golden AMI.

Let me tell you about Packer also;

  • Packer allows you to build images for multiple platforms like AWS, Azure, GCP, and Docker, etc. using same configuration files.
  • Packer is simple in terms of logging and debugging as the output is clearly shown in the command-line when the image is built.
  • Packer uses JSON files to build the components which are simple commands and can be easily integrated with CI/CD pipelines.
  • Packer has built-in support for using various configuration management tools like Ansible, Chef, and Puppet along with Shell and PowerShell script support for installing software.
  • Packer is distributed as a lightweight binary and it is controlled using CLI.

Installing Packer on AWS EC2 Centos

First, you need to have an EC2 instance running on AWS with admin IAM role attached for testing purposes. I will be using an EC2 instance with CentOS 7 AMI. We also need to get the ssh public key for the instance and save it as packer on AWS key pairs which is located in EC2.

For your operating system you can check the HashiCorp Packer official installation page right from here;

Below I have installation commands for Linux CentOS 7.

Second, we will install yum config manager to manage our repositories then we will add the official HashiCorp Linux repository then install Packer.

  • sudo yum install -y yum-utils
  • sudo yum-config-manager --add-repo
  • sudo yum -y install packer
  • packer --version

Now we can start creating a template. Let’s first create a folder called WordPress then we need to create a file inside that which will be called dev.pkr.hcl

Copy the following into the file `dev.pkr.hcl`

Below code will create an updated CentOS 7 Kernel and WordPress installed AMI.

packer {
	required_plugins {
		amazon = {
			version = ">= 0.0.1"
			source = ""

variable "ssh_private_key_file" {
    default = "/home/centos/.ssh/id_rsa"

// save your local machine ssh public key to aws then replace the ssh keypair name below.
variable "ssh_keypair_name" {
    default = "packer"

variable "source_ami_name" {
    default = "CentOS Linux 7 x86_64 HVM EBS ENA 1901_01-b7ee8a69-ee97-4a49-9e68-afaee216db2e-*"
variable "instance_type" {
    default = "t2.micro"
variable "ssh_username" {
    default = "centos"
variable "ami_name" {
    default = "bastion_wordpress_kernel_updated"
variable "region" {
    default = "us-east-1"
variable "owners" {
    default = "679593333241"

source "amazon-ebs" "image" {
	ami_name             = "${var.ami_name} {{timestamp}}"
	ssh_private_key_file = "${var.ssh_private_key_file}"
	ssh_keypair_name     = "${var.ssh_keypair_name}"
	instance_type        = "${var.instance_type}"
	ssh_username         = "${var.ssh_username}"
	region               = "${var.region}"
	source_ami_filter {
		most_recent = true
		owners      = ["${var.owners}"]
		filters = {
			name                = "${var.source_ami_name}"
			virtualization-type = "hvm"
			root-device-type    = "ebs"
	run_tags = {
		Name = "Packer instance for ${var.source_ami_name}"

build {
	sources = [
	provisioner "shell" {
		inline = [
			"echo Installing Telnet",
            "sudo yum update kernel -y",
			"sudo yum install telnet -y",  #Change for ubuntu
            "sudo yum install elinks -y",   #Change for ubuntu
            "sudo yum install httpd -y",
            "sudo yum install php -y",
            "sudo systemctl restart httpd",
            "sudo systemctl enable httpd",
            "sudo yum install wget -y",
            "sudo wget",
            "sudo tar -xf wordpress-4.0.32.tar.gz -C /var/www/html/",
            "sudo mv /var/www/html/wordpress/* /var/www/html/",
            "sudo yum install php-mysql -y",
            "sudo systemctl restart httpd",
            "sudo chown -R apache:apache /var/www/html/",
            "sudo systemctl restart httpd"
	provisioner "breakpoint" {
		note = "Waiting for your verification"

Inside our WordPress folder let’s run some packer commands to start building our AMI.

packer init .

packer validate .

packer build .

Packer will start an EC2 instance to build our AMI and you can verify if the tools are installed by ssh to the packer created instance from our EC2 instance. If tools are installed correctly please verify and continue for packer build in our terminal.

Build ‘amazon-ebs.image’ finished after 8 minutes 5 seconds.

==> Wait completed after 8 minutes 5 seconds

==> Builds finished. The artifacts of successful builds are:
–> amazon-ebs.image: AMIs were created:
us-east-1: ami-055afae0b53a0262e

For me it took 8 minutes 5 seconds to complete and make an AMI. You can make this faster by changing the instance type at above packer code. Created WordPress & Kernel updated AMI will be located under EC2 > Images > AMI’s > Owned by me

About the Author

Emir profile.

Emir Kor

Leave a Reply

Your email address will not be published.

Related Blog Posts
A security model for developers
Software security is more important than ever, but developing secure applications is more confusing than ever. TLS, mTLS, RBAC, SAML, OAUTH, OWASP, GDPR, SASL, RSA, JWT, cookie, attack vector, DDoS, firewall, VPN, security groups, exploit, […]
Building Better Data Visualization Experiences: Part 1 of 2
Through direct experience with data scientists, business analysts, lab technicians, as well as other UX professionals, I have found that we need a better understanding of the people who will be using our data visualization products in order to build them. Creating a product utilizing data with the goal of providing insight is fundamentally different from a typical user-centric web experience, although traditional UX process methods can help.
Kafka Schema Evolution With Java Spring Boot and Protobuf
In this blog I will be demonstrating Kafka schema evolution with Java, Spring Boot and Protobuf.  This app is for tutorial purposes, so there will be instances where a refactor could happen. I tried to […]
Redis Bitmaps: Storing state in small places
Redis is a popular open source in-memory data store that supports all kinds of abstract data structures. In this post and in an accompanying example Java project, I am going to explore two great use […]