Filters
How to search
  • Plain words find names, texts and examples.
  • "two words" finds the exact phrase.
  • --name or -x finds an option.
  • #word looks only inside commands.
  • @grep finds lessons and labs that use grep.
  • Filters: cat:network · in:labs · in:notes · level:rhcsa · ch:8 · root:yes. Put ! before a word to leave it out. OR between words means one of them.
  • ↑ ↓ to move · Enter to open · Esc to close · / to search

packer

Build golden machine images (Azure, AWS, VMware, QEMU) from code — the same hardened base for every server.

Level
DevSecOps service
Group
Infrastructure as Code and cloud
Needs root
No
Package
packer

What it does

Packer starts a temporary VM from a base image, runs provisioners (shell scripts, Ansible, file uploads) to install and harden it, then saves the result as a new image (Azure Managed Image / Compute Gallery, AWS AMI, qcow2). Terraform then creates servers from that image. This is the immutable infrastructure idea: you replace servers with a new image instead of patching them by hand.

Templates are written in HCL (*.pkr.hcl) with source (where to build) and build (what to do) blocks.

How to write it

packer init|fmt|validate|build [OPTIONS] TEMPLATE_OR_DIR

Main parts

Commands

init DIR
Install the plugins in required_plugins.
fmt DIR
Format templates.
validate DIR
Check templates.
build DIR
Build the image(s).
inspect DIR
Show the parts of a template.
console
Try expressions.
plugins install|installed
Manage plugins.

Options 8

Most used

build flags

-var 'k=v' / -var-file=FILE
Variables.
-only=SOURCE
Build only some sources.
-except=SOURCE
Skip some sources.
-force
Replace an existing image with the same name.
-on-error=ask|abort|cleanup
What to do when a step fails (ask = keep the VM to debug).
-parallel-builds=N
Parallel builds.
-debug
Step by step, show keys.
-timestamp-ui
Timestamps in the output.

Examples 10

$ run as a normal user# run as root (or with sudo)

  1. 1The workflow

    packer init .
    packer fmt .
    packer validate .
    packer build .
  2. 2An Azure image template

    cat rhel-base.pkr.hcl
    packer {
      required_plugins {
        azure   = { source = "github.com/hashicorp/azure", version = "~> 2" }
        ansible = { source = "github.com/hashicorp/ansible", version = "~> 1" }
      }
    }
    source "azure-arm" "rhel" {
      use_azure_cli_auth                = true
      location                          = "westeurope"
      vm_size                           = "Standard_B2s"
      os_type                           = "Linux"
      image_publisher                   = "RedHat"
      image_offer                       = "RHEL"
      image_sku                         = "9-lvm-gen2"
      managed_image_name                = "rhel9-base-${formatdate("YYYYMMDD", timestamp())}"
      managed_image_resource_group_name = "rg-images"
    }
    build {
      sources = ["source.azure-arm.rhel"]
      provisioner "ansible" { playbook_file = "harden.yml" }
      provisioner "shell" {
        inline = ["sudo dnf -y update", "sudo /usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"]
      }
    }
  3. 3Build with variables

    packer build -var-file=prod.pkrvars.hcl .
  4. 4Build one source only

    packer build -only=azure-arm.rhel .
  5. 5Keep the VM when a step fails, to debug

    packer build -on-error=ask .
  6. 6Build a local QEMU image for the lab

    packer build -only=qemu.rhel9 .
  7. 7Use the image in Terraform

    cat vm.tf
    data "azurerm_image" "base" {
      name_regex          = "^rhel9-base-"
      sort_descending     = true
      resource_group_name = "rg-images"
    }
  8. 8Scan the built image in CI

    trivy vm --scanners vuln azure:///subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-images/providers/Microsoft.Compute/images/rhel9-base-20261027
  9. 9Check the template parts

    packer inspect .
  10. 10Rebuild every month in a pipeline

    cat .github/workflows/image.yml
    on: { schedule: [{ cron: "0 3 1 * *" }] }

Watch out

  • Remove SSH keys, shell history and machine IDs at the end (deprovision), or every server shares them.
  • Do not bake secrets into images — fetch them at boot (Key Vault, cloud-init).

Files

*.pkr.hcl
Templates.
*.pkrvars.hcl
Variable values.

Tips to remember

  • Version images by date and keep a few old ones for rollback.

Exit codes

0Success.
1Error.