← All TILs · packer

What Packer actually is, and how it works

packer - 2026-09-17

Second entry in the HashiCorp infrastructure series. Terraform/OpenTofu manages the lifecycle of infrastructure over time; Packer's job stops the moment it hands you a finished image. That single-shot, no-state nature is the thing to understand before anything else about it.

The template pieces

Per Packer's own HCL2 template docs, a template is built from a small set of block types:

graph TD
    S[source: builder config<br/>AMI, qcow2, Proxmox template...] --> B[build: ties sources<br/>to provisioners/post-processors]
    B --> P1[provisioner: shell]
    B --> P2[provisioner: Ansible]
    B --> P3[provisioner: file upload]
    P1 --> PP1[post-processor: compress]
    P2 --> PP1
    P3 --> PP1
    PP1 --> PP2[post-processor: upload / manifest]

This is the same HCL2 language Terraform/OpenTofu uses — same variable/local syntax, same .pkrvars.hcl convention mirroring .tfvars. If the syntax from the previous entry in this series looked familiar, that's why.

What actually happens during a build

sequenceDiagram
    actor You
    participant Packer
    participant Instance as Temporary build instance
    participant Artifact as Artifact store

    You->>Packer: packer build template.pkr.hcl
    Packer->>Instance: launch from the source block
    Packer->>Instance: run provisioners (shell, Ansible, etc)
    Instance-->>Packer: machine is configured
    Packer->>Artifact: run post-processors (compress, upload, manifest)
    Packer->>Instance: destroy
    Packer-->>You: artifact ready (AMI, qcow2, template, container image)

packer build launches a genuinely real, temporary instance of whatever the source describes, runs every provisioner against it in order — same as configuring any other machine — then runs the post-processor chain against the result, and only then tears the temporary instance down. What survives is the artifact; the instance that built it doesn't.

No state file, on purpose

Terraform/OpenTofu's state file exists because it has to reconcile a running, changing resource against desired config indefinitely. Packer never has that problem: once packer build finishes, there's nothing left for it to track — no drift to detect, because there's no persistent resource left under its management. Run the same template again and it builds a brand-new artifact from scratch; it doesn't diff against the last one. That's also why "updating" a Packer-built image almost always means building a new one and replacing references to it (in a Terraform variable, an autoscaling group's launch template, whatever consumes the artifact) rather than patching the existing image in place.

Where this fits with the rest of the series

The artifact a Packer build produces is exactly the kind of thing a Terraform/OpenTofu resource block references — an AMI ID, a template name — to actually provision infrastructure from. Next up: Nomad, and then how all three tie together.

Created 2026-09-17T19:07:18+02:00, updated 2026-09-27T17:29:34+02:00 · History · Edit