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
Natively Compiled Java on Google App Engine
Google App Engine is a platform-as-a-service product that is marketed as a way to get your applications into the cloud without necessarily knowing all of the infrastructure bits and pieces to do so. Google App […]
Building Better Data Visualization Experiences: Part 2 of 2
If you don't have a Ph.D. in data science, the raw data might be difficult to comprehend. This is where data visualization comes in.
Unleashing Feature Flags onto Kafka Consumers
Feature flags are a tool to strategically enable or disable functionality at runtime. They are often used to drive different user experiences but can also be useful in real-time data systems. In this post, we’ll […]
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, […]