Command Palette

Search for a command to run...

GitHubGitHub

HashiCorp Packer Installation Guide

Install Packer 1.16, write HCL2 templates, build machine images for AWS, Azure, GCP and QEMU, and produce signed provenance attestations for your supply chain.

Packer builds identical machine images for multiple platforms from a single configuration. One template, many clouds — with the same provisioners and the same result everywhere.

System Requirements

  • A 64-bit operating system (Linux, macOS, Windows, FreeBSD)
  • Packer is a single static binary — no runtime dependencies
  • Credentials for the target platform (AWS, Azure, GCP, Proxmox, QEMU, …)
  • For local builds: a hypervisor such as QEMU, VirtualBox, VMware or Hyper-V

Installation Instructions

Ubuntu / Debian (apt)

# Add the HashiCorp signing key
wget -O - https://apt.releases.hashicorp.com/gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
 
# Add the repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/hashicorp.list
 
# Install
sudo apt update
sudo apt install -y packer
 
packer version

Verifying the Installation

# Version
packer version
 
# List the available plugins
packer plugins installed
 
# Format a template
packer fmt .
 
# Validate a template
packer validate .

Your First Template

Create template.pkr.hcl:

packer {
  required_plugins {
    amazon = {
      source  = "github.com/hashicorp/amazon"
      version = ">= 1.3.0"
    }
  }
}
 
variable "aws_region" {
  type    = string
  default = "eu-central-1"
}
 
variable "ami_name" {
  type    = string
  default = "app-base-{{timestamp}}"
}
 
source "amazon-ebs" "ubuntu" {
  region        = var.aws_region
  instance_type = "t3.micro"
  ami_name      = var.ami_name
  source_ami    = "ami-0abcdef1234567890" # Ubuntu 24.04 LTS
  ssh_username  = "ubuntu"
  ami_name_filter = "app-base-*"
  tags = {
    Name        = var.ami_name
    built_by    = "packer"
    build_date  = "{{timestamp}}"
  }
}
 
build {
  name    = "ubuntu-base"
  sources = ["source.amazon-ebs.ubuntu"]
 
  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx",
      "sudo systemctl enable nginx",
    ]
  }
 
  provisioner "file" {
    source = "./nginx.conf"
    destination = "/tmp/nginx.conf"
  }
 
  post-processor "manifest" {
    output     = "manifest.json"
    strip_path = true
  }
}
# Install the plugins the template needs
packer init .
 
# Validate the template
packer validate .
 
# Build it
packer build .
 
# Build only one source, or exclude one
packer build -only="amazon-ebs.ubuntu" .
packer build -except="amazon-ebs" .

Building on Other Platforms

Packer uses the same template structure for every platform — only the source block changes.

# Azure
source "azure-arm" "ubuntu" {
  location          = "westeurope"
  vm_size           = "Standard_B1s"
  image_source_id   = "/subscriptions/.../sourceImage"
  ssh_username      = "packer"
  image_offer       = "0001-com-ubuntu-server-jammy"
  image_sku         = "22_04-lts-gen2"
}
 
# Google Cloud
source "googlecompute" "ubuntu" {
  project_id = "my-project"
  source_image_family = "ubuntu-2404-lts-amd64"
  image_name  = "app-base-{{timestamp}}"
  ssh_username = "packer"
  zone         = "europe-west4-a"
  machine_type = "e2-medium"
}

Build Attestations (SLSA)

Packer 1.16 can emit and verify signed provenance for the images it builds, so consumers can prove where an image came from:

post-processor "provenance" {
  only = ["docker.*"]
  # Sign with a local PEM key
  sign = "./cosign.key"
  # ...or with a cloud KMS key
  # sign = "awskms:///alias/cosign"
}
# Verify an attestation
packer verify-attestation --path "pkg:docker/your-image@sha256:..." \
  --certificate "chain.pem" --key "cosign.key"

Upgrading

# Upgrade the binary
sudo apt update && sudo apt install --only-upgrade packer
 
# Update the plugins
packer plugins update
 
# Check what is installed
packer plugins installed

Troubleshooting

Best Practices

  1. Declare and pin plugins in required_plugins, and commit .packer.lock.hcl.
  2. Version your images — {{timestamp}} or a semantic version, never latest.
  3. Build one base image and layer on top instead of rebuilding everything.
  4. Use manifest post-processors so you know which artefact came from which build.
  5. Produce provenance attestations for images you publish.
  6. Keep templates free of secrets — use environment variables or a secrets manager.
  7. Run packer validate and packer fmt -check in CI before every build.
  8. Tag images with the source commit so you can trace an image back to the code.

Next Steps