HashiCorp Packer: Automated Multi-Platform Image Building and Golden Image Creation

Complete guide to building consistent machine images across cloud platforms using Packer with HCL2 and JSON templates

Featured image



Overview

In modern infrastructure management, creating consistent and reproducible machine images across multiple platforms remains a critical challenge.

HashiCorp Packer addresses this need by providing a powerful automation tool for building identical machine images from a single source template across various platforms.

This comprehensive guide explores Packer’s capabilities for creating Golden Images - standardized, pre-configured machine images that serve as the foundation for consistent deployments.

We’ll cover everything from basic installation to advanced multi-platform image building, including integration with Vagrant, AWS, GCP, and Azure.

Packer excels at Infrastructure as Code principles, enabling teams to version control their image configurations and automate the entire image building pipeline.

When combined with Terraform and Vagrant, Packer becomes an essential component of complete infrastructure automation workflows.



What is HashiCorp Packer?

Packer is an open-source tool for creating identical machine images for multiple platforms from a single source configuration. It automates the process of building, provisioning, and packaging machine images, making it ideal for creating “Golden Images” that teams can use consistently across their cloud infrastructure.


Core Capabilities:


Key Benefits:

Golden Image Advantages



Installation and Setup


Step 1: Install Packer

# CentOS/RHEL Installation
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install packer

# Ubuntu/Debian Installation
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install packer

# macOS Installation
brew tap hashicorp/tap
brew install hashicorp/tap/packer

# Verify installation
packer version


Step 2: Install Supporting Tools

# For local virtualization (KVM/QEMU)
# CentOS/RHEL
sudo yum -y install qemu libvirt libvirt-devel ruby-devel gcc qemu-kvm libguestfs-tools

# Ubuntu/Debian
sudo apt install -y qemu qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager

# For Vagrant integration
sudo yum -y install vagrant  # or apt install vagrant
vagrant plugin install vagrant-libvirt
vagrant plugin install vagrant-mutate

# For cloud provider CLI tools
# AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip && sudo ./aws/install

# Google Cloud SDK
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
gcloud init


Step 3: Enable Command Autocompletion

# Enable Packer autocompletion
packer -autocomplete-install

# Reload shell configuration
source ~/.bashrc  # or ~/.zshrc

# Test autocompletion
packer <TAB><TAB>


Step 4: Resolve Binary Conflicts (If Needed)

# Check for conflicting packer binaries
which packer
ls -la /usr/sbin/packer

# If cracklib-packer conflict exists
sudo rm -rf /usr/sbin/packer
sudo ln -s /usr/bin/packer /usr/sbin/packer

# Verify correct packer is active
packer version
# Should show: Packer v1.x.x



Packer CLI Commands


Core Commands Overview

# Essential Packer commands
packer init        # Install missing plugins
packer validate    # Validate template syntax
packer build       # Build images from template
packer inspect     # Show template components
packer fmt         # Format HCL2 templates
packer console     # Interactive console for testing


Command: packer init

# Initialize plugins for a template
packer init -h

Usage: packer init [options] [config.pkr.hcl|folder/]

  Install all the missing plugins required in a Packer config.
  This is the first command that should be executed when working 
  with a new or existing template.

Options:
  -upgrade                     Update installed plugins to latest version
  
# Example usage
packer init .
packer init templates/
packer init -upgrade aws-template.pkr.hcl


Command: packer build

# Build images from templates
packer build -h

Usage: packer build [options] TEMPLATE

  Execute multiple builds in parallel as defined in the template.
  Various artifacts created by the template will be outputted.

Options:
  -color=false                  Disable color output
  -debug                        Enable debug mode for builds
  -except=foo,bar,baz          Run all builds except these
  -only=foo,bar,baz            Build only specified builds
  -force                       Force build, delete existing artifacts
  -parallel-builds=1           Number of parallel builds (0 = no limit)
  -var 'key=value'             Template variables
  -var-file=path               Variable file (JSON/HCL2)

# Example usage
packer build template.pkr.hcl
packer build -var 'region=us-west-2' aws-template.pkr.hcl
packer build -var-file=variables.pkrvars.hcl template.pkr.hcl
packer build -only=amazon-ebs.ubuntu template.pkr.hcl


Command: packer validate

# Validate template configuration
packer validate template.pkr.hcl
packer validate -var-file=vars.pkrvars.hcl template.pkr.hcl

# Example output for valid template:
# The configuration is valid.

# Example output for invalid template:
# Error: Invalid template syntax


Command: packer plugins

# Plugin management commands
packer plugins install github.com/hashicorp/amazon
packer plugins installed
packer plugins required .
packer plugins remove github.com/hashicorp/amazon

# List available plugins
packer plugins installed
# Example output:
# github.com/hashicorp/amazon v1.2.1
# github.com/hashicorp/googlecompute v1.0.16



Template Formats: HCL2 vs JSON


HCL2 (HashiCorp Configuration Language 2) is the modern template format used across HashiCorp tools. It provides better syntax, modularity, and advanced features compared to JSON.



Legacy JSON Format



Multi-Platform Image Building


AWS AMI Creation


Google Cloud Platform Images


Azure VM Images



Vagrant Box Creation


Local Vagrant Box with QEMU/KVM


Vagrant Setup Scripts



Template Migration and Management


JSON to HCL2 Migration

# Upgrade existing JSON template to HCL2
packer hcl2_upgrade -with-annotations template.json

# This creates template.json.pkr.hcl with:
# - Detailed comments
# - Modern HCL2 syntax
# - Variable type definitions
# - Plugin requirements


Example Migration Process


Template Organization Best Practices

# Recommended directory structure
packer-templates/
├── aws/
│   ├── variables.pkrvars.hcl
│   ├── ubuntu.pkr.hcl
│   ├── centos.pkr.hcl
│   └── windows.pkr.hcl
├── gcp/
│   ├── variables.pkrvars.hcl
│   └── ubuntu.pkr.hcl
├── vagrant/
│   ├── ubuntu-box.pkr.hcl
│   └── centos-box.pkr.hcl
├── scripts/
│   ├── common/
│   ├── aws/
│   ├── gcp/
│   └── vagrant/
└── http/
    ├── preseed.cfg
    └── kickstart.cfg



Advanced Provisioning Strategies


Ansible Integration


Docker Image Building


Windows Image Building



CI/CD Integration and Automation


GitHub Actions Workflow


Jenkins Pipeline

// Jenkinsfile
pipeline {
    agent any
    
    environment {
        PACKER_VERSION = '1.9.4'
        AWS_REGION = 'us-west-2'
    }
    
    parameters {
        choice(
            name: 'BUILD_TYPE',
            choices: ['validate', 'build', 'build-all'],
            description: 'Type of build to perform'
        )
        choice(
            name: 'TEMPLATE',
            choices: ['ubuntu', 'centos', 'amazon-linux', 'all'],
            description: 'Template to build'
        )
    }
    
    stages {
        stage('Setup') {
            steps {
                script {
                    // Download and setup Packer
                    sh """
                        wget -O packer.zip https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip
                        unzip -o packer.zip
                        chmod +x packer
                        ./packer version
                    """
                }
            }
        }
        
        stage('Initialize') {
            steps {
                sh './packer init packer/'
            }
        }
        
        stage('Validate') {
            steps {
                script {
                    if (params.TEMPLATE == 'all') {
                        sh '''
                            for template in packer/*.pkr.hcl; do
                                echo "Validating $template"
                                ./packer validate "$template"
                            done
                        '''
                    } else {
                        sh "./packer validate packer/${params.TEMPLATE}.pkr.hcl"
                    }
                }
            }
        }
        
        stage('Build') {
            when {
                anyOf {
                    equals expected: 'build', actual: params.BUILD_TYPE
                    equals expected: 'build-all', actual: params.BUILD_TYPE
                }
            }
            steps {
                script {
                    withCredentials([
                        string(credentialsId: 'aws-access-key', variable: 'AWS_ACCESS_KEY_ID'),
                        string(credentialsId: 'aws-secret-key', variable: 'AWS_SECRET_ACCESS_KEY')
                    ]) {
                        if (params.TEMPLATE == 'all') {
                            sh '''
                                for template in packer/*.pkr.hcl; do
                                    echo "Building $template"
                                    ./packer build -var "region=${AWS_REGION}" "$template"
                                done
                            '''
                        } else {
                            sh "./packer build -var 'region=${AWS_REGION}' packer/${params.TEMPLATE}.pkr.hcl"
                        }
                    }
                }
            }
        }
        
        stage('Archive Artifacts') {
            steps {
                archiveArtifacts artifacts: 'manifest.json', allowEmptyArchive: true
                publishHTML([
                    allowMissing: false,
                    alwaysLinkToLastBuild: true,
                    keepAll: true,
                    reportDir: '.',
                    reportFiles: 'manifest.json',
                    reportName: 'Packer Build Report'
                ])
            }
        }
    }
    
    post {
        always {
            cleanWs()
        }
        success {
            echo 'Packer build completed successfully!'
        }
        failure {
            echo 'Packer build failed!'
        }
    }
}



Monitoring and Logging


Build Monitoring Script



Best Practices and Security


Security Hardening Template


Environment-Specific Variables


Build Validation and Testing



Conclusion

HashiCorp Packer revolutionizes infrastructure image management by providing a unified, automated approach to building consistent machine images across multiple platforms. The transition from manual image creation to Infrastructure as Code principles fundamentally improves deployment reliability, security, and operational efficiency.


Key Achievements:

  1. Multi-Platform Consistency: Single template creates identical images across AWS, GCP, Azure, and local environments
  2. Automated Golden Images: Standardized, pre-configured images reduce deployment time and configuration drift
  3. Security Integration: Built-in security hardening and compliance validation
  4. CI/CD Pipeline Integration: Automated image building and testing workflows


Operational Benefits:


Future Enhancements:

Mastering Packer enables organizations to achieve true Infrastructure as Code maturity, where every component of the infrastructure stack is automated, versioned, and reproducible. The combination of consistent image building, security hardening, and multi-platform support makes Packer an essential tool for modern cloud infrastructure teams.

“Packer transforms image management from a manual, error-prone process into an automated, reliable foundation for scalable infrastructure.”



References