How to Install Packer for Machine Image Automation on RHEL 7

Packer, developed by HashiCorp, is an open-source tool that enables you to create identical machine images for multiple platforms from a single source configuration. Whether you are building AMIs for AWS, OVA files for VMware, or disk images for on-premises hypervisors, Packer automates the entire process — dramatically reducing the time spent on golden image maintenance. On Red Hat Enterprise Linux 7, Packer integrates seamlessly into infrastructure automation pipelines and pairs naturally with Terraform for a complete infrastructure-as-code workflow. This guide walks you through downloading and installing Packer on RHEL 7, writing your first HCL2 template, working with builders and provisioners, and connecting Packer-built artifacts to Terraform.

Prerequisites

  • RHEL 7 server or workstation with sudo or root access
  • Active internet connection to reach HashiCorp releases
  • unzip installed: yum install -y unzip
  • Optional: AWS CLI configured if you plan to use the amazon-ebs builder
  • Optional: VirtualBox installed if you plan to use the virtualbox-iso builder
  • Terraform installed if you plan to consume Packer artifacts downstream

Step 1: Download the Packer Binary from HashiCorp

HashiCorp distributes Packer as a single pre-compiled binary. Visit the HashiCorp releases page or use curl to download the appropriate Linux AMD64 archive directly to your RHEL 7 machine.

# Check the latest stable version on the releases page, then substitute below.
# Example using Packer 1.10.3
PACKER_VERSION="1.10.3"
curl -fsSL "https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip" 
     -o /tmp/packer.zip

# Verify the checksum
curl -fsSL "https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_SHA256SUMS" 
     -o /tmp/packer_SHA256SUMS
sha256sum -c /tmp/packer_SHA256SUMS --ignore-missing

You should see output like packer_1.10.3_linux_amd64.zip: OK. If the checksum fails, re-download the archive; do not proceed with a corrupted binary.

Step 2: Install Packer and Configure PATH

Extract the binary and place it in a directory that is on your system PATH. /usr/local/bin is the conventional location for locally installed binaries on RHEL 7.

unzip /tmp/packer.zip -d /tmp/packer_extract
sudo mv /tmp/packer_extract/packer /usr/local/bin/packer
sudo chmod +x /usr/local/bin/packer

# Confirm the installation
packer --version

Expected output:

1.10.3

If you receive a command not found error, verify that /usr/local/bin is included in your PATH:

echo $PATH
# If missing, add it permanently:
echo 'export PATH=$PATH:/usr/local/bin' >> ~/.bash_profile
source ~/.bash_profile

Step 3: Initialize a Packer Project with HCL2

Packer historically used JSON templates, but the modern approach — and the format used in all new documentation — is HCL2 (HashiCorp Configuration Language version 2), which uses .pkr.hcl file extensions. HCL2 offers variable interpolation, reusable modules, and much more readable syntax.

Create a working directory for your first Packer project:

mkdir ~/packer-demo && cd ~/packer-demo

Create the main template file:

cat > build.pkr.hcl <<'EOF'
packer {
  required_plugins {
    amazon = {
      version = ">= 1.3.0"
      source  = "github.com/hashicorp/amazon"
    }
  }
}

variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "base_ami" {
  type    = string
  default = "ami-0c02fb55956c7d316"  # RHEL 7 HVM in us-east-1 (example)
}

source "amazon-ebs" "rhel7_base" {
  region          = var.aws_region
  source_ami      = var.base_ami
  instance_type   = "t3.micro"
  ssh_username    = "ec2-user"
  ami_name        = "rhel7-golden-{{timestamp}}"
  ami_description = "RHEL 7 golden image built with Packer"

  tags = {
    Builder     = "Packer"
    Environment = "production"
  }
}

build {
  name    = "rhel7-ami"
  sources = ["source.amazon-ebs.rhel7_base"]

  provisioner "shell" {
    inline = [
      "sudo yum update -y",
      "sudo yum install -y wget curl git vim",
      "sudo systemctl enable firewalld",
      "sudo systemctl start firewalld"
    ]
  }
}
EOF

Step 4: Working with the VirtualBox Builder

If you need a local virtualbox-iso image rather than an AWS AMI, the configuration differs slightly. This builder boots a VM from an ISO, installs the OS automatically via a Kickstart or Preseed file, and then runs provisioners.

cat > virtualbox.pkr.hcl <<'EOF'
source "virtualbox-iso" "rhel7_local" {
  iso_url           = "http://mirror.example.com/rhel-server-7.9-x86_64-dvd.iso"
  iso_checksum      = "sha256:your_iso_sha256_here"
  vm_name           = "rhel7-base"
  guest_os_type     = "RedHat_64"
  disk_size         = 20480
  memory            = 2048
  cpus              = 2
  headless          = true

  boot_command = [
    " inst.ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg"
  ]
  http_directory    = "http"
  shutdown_command  = "sudo /sbin/halt -h -p"
  ssh_username      = "vagrant"
  ssh_password      = "vagrant"
  ssh_timeout       = "30m"
  output_directory  = "output-rhel7"
  format            = "ova"
}

build {
  sources = ["source.virtualbox-iso.rhel7_local"]

  provisioner "shell" {
    script = "scripts/provision.sh"
  }
}
EOF

Step 5: Using Ansible as a Provisioner

Shell scripts work well for simple provisioning, but Ansible offers idempotency, roles, and a much richer module ecosystem. Packer includes a built-in Ansible provisioner.

# Install Ansible on the machine running Packer
sudo yum install -y epel-release
sudo yum install -y ansible

# Update the build block in your .pkr.hcl to use ansible:
# provisioner "ansible" {
#   playbook_file   = "./playbooks/site.yml"
#   user            = "ec2-user"
#   use_proxy       = false
#   extra_arguments = ["--extra-vars", "env=production"]
# }

Create a minimal playbook at playbooks/site.yml:

---
- hosts: all
  become: yes
  tasks:
    - name: Ensure useful packages are installed
      yum:
        name:
          - vim
          - wget
          - curl
          - net-tools
        state: present

    - name: Enable and start firewalld
      systemctl:
        name: firewalld
        enabled: yes
        state: started

Step 6: Initialize Plugins and Run a Build

Before running a build that uses external plugins (such as the Amazon plugin), you must initialize the project so Packer can download the required plugin binaries:

cd ~/packer-demo
packer init .

Validate the template syntax before executing a full build:

packer validate build.pkr.hcl

Run the actual build:

packer build build.pkr.hcl

# Pass variable overrides at the command line:
packer build -var "aws_region=eu-west-1" build.pkr.hcl

# Use a variables file:
packer build -var-file="prod.pkrvars.hcl" build.pkr.hcl

Packer will output progress for each step: booting the instance, running SSH, executing provisioners, creating the AMI snapshot, and finally printing the artifact ID.

Step 7: Inspecting Built Artifacts

After a successful build, Packer logs the artifact identifiers. For the Amazon EBS builder, this is the AMI ID. You can also use the Packer inspect subcommand to examine template metadata without running a build:

# Inspect a template to see sources, builds, and variables
packer inspect build.pkr.hcl

# Sample output:
# Packer Inspect: HCL2 config
# 
# Sources:
#   amazon-ebs.rhel7_base
# 
# Builds:
#   rhel7-ami
#     sources:  amazon-ebs.rhel7_base
#     provisioners: shell

# After a build, Packer writes a manifest if you add the manifest post-processor:
# post-processor "manifest" {
#   output = "packer-manifest.json"
# }
cat packer-manifest.json

Step 8: Integrating Packer Artifacts with Terraform

A common pattern is to build AMIs with Packer and then reference them in Terraform configurations using the aws_ami data source, ensuring your infrastructure always uses the latest golden image.

# In your Terraform configuration (main.tf):
data "aws_ami" "rhel7_golden" {
  most_recent = true
  owners      = ["self"]

  filter {
    name   = "name"
    values = ["rhel7-golden-*"]
  }

  filter {
    name   = "tag:Builder"
    values = ["Packer"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.rhel7_golden.id
  instance_type = "t3.medium"

  tags = {
    Name = "web-server"
  }
}

This approach decouples image building from infrastructure provisioning. Packer runs in CI/CD to produce a fresh AMI on every approved OS update, while Terraform always picks up the newest artifact automatically.

Conclusion

Packer transforms machine image creation from a manual, error-prone task into a reproducible, version-controlled process. On RHEL 7, you can leverage Packer to build AWS AMIs, VirtualBox OVAs, and other artifact formats using the same HCL2 template with different source blocks. By combining shell and Ansible provisioners, you can enforce a consistent software baseline across all images. The integration with Terraform closes the loop on the infrastructure-as-code lifecycle — Packer owns image creation, Terraform owns deployment. As a next step, consider adding Packer builds to your Jenkins or GitLab CI pipeline so that every merge to your infrastructure repository triggers a fresh golden image build automatically.