Use Packer HCL2 Variable Files to Keep Image Builds DRY Across Environments
Keep Packer image builds DRY by using HCL2 variable blocks and external .pkrvars.hcl files. One template, multiple environments, and validation before every build.
01 Oct 2026, 19:46 UTC

Problem: Repeating Code for Every Environment
When building AMIs for dev, test, and prod, teams often copy a Packer template and tweak a handful of values—AMI name, tags, base image, or region. That duplication makes the repository hard to maintain and increases the risk of drift between environments.
HCL2 & Variable Blocks: The Packer Solution
Packer’s HCL2 syntax lets you declare variables directly in the template:
variable "ami_name" {
type = string
default = "my-base-ami"
}
source "amazon-ebs" "build" {
ami_name = var.ami_name
tags = {
Environment = var.env
}
}
The var. prefix pulls the value at build time. Variables can be overridden on the command line with -var or, more cleanly, by loading an external .pkrvars.hcl file with -var-file. This keeps the template identical while allowing environment‑specific overrides.
Concrete Example: dev, test, prod
1. Create a single template image.pkr.hcl:
variable "env" {
type = string
}
variable "base_ami" {
type = string
}
source "amazon-ebs" "build" {
ami_name = "${var.env}-app-ami-${timestamp() }"
source_ami = var.base_ami
region = "us-east-1"
tags = {
Environment = var.env
Project = "my-app"
}
}
build {
sources = ["source.amazon-ebs.build"]
}
2. Create variable files:
# dev.pkrvars.hcl
env = "dev"
base_ami = "ami-0abcd1234efgh5678"
# test.pkrvars.hcl
env = "test"
base_ami = "ami-1abcd1234efgh5678"
# prod.pkrvars.hcl
env = "prod"
base_ami = "ami-2abcd1234efgh5678"
3. Validate the template once:
packer validate image.pkr.hcl
If a variable is missing or of the wrong type, Packer will fail before the build starts.
4. Build for a specific environment:
packer build -var-file=dev.pkrvars.hcl image.pkr.hcl
During the build, Packer substitutes var.env and var.base_ami with the values from dev.pkrvars.hcl. The resulting AMI will have a name like dev-app-ami-20261001T123456Z and the tag Environment=dev. Repeat with test.pkrvars.hcl or prod.pkrvars.hcl.
Trade‑Offs & Limitations
- Order matters: The
-var-fileflag must come after the template path; otherwise Packer will complain about undefined variables. - Sensitive data: Variable files should not be committed to source control. Mark sensitive variables with
sensitive = trueand use a secrets manager or environment variables for production values. - Complex logic: While HCL2 supports loops and conditionals, overusing them can make the template harder to read. Keep the logic simple and document any non‑obvious expressions.
Actionable Takeaway
Adopt a single HCL2 template and separate .pkrvars.hcl files for each environment. Run packer validate on every change to catch variable errors early, and keep sensitive values out of version control. This pattern keeps your image builds DRY, consistent, and fully version‑controlled.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.