What is a Multipurpose Packer Templates
We’ve now gotten to a point that I have probably the most experience with, and that is with Packer. After Terraform, Packer was the next HashiCorp tool that I picked up. Thankfully, the syntax moved from JSON to HCL a couple of years ago at this point.
Limitations
The downside with Packer are some of its limitations, specifically with meta-arguments.
Workarounds
So there are a couple of workarounds.
Dynamic Blocks
Dynamic blocks are similar to Terraform, where you can run a foreach against it, and it will loop through the input.
Shared Resources
When using shared scripts or files, I would recommend using environment_vars on the provisioners and have them specific for the build or source platform you will build on.
Additional Support
There are a couple of other ways I keep my templates generalized.
Tree Structure
The tree below is a work in progress, which I will later reference, but it is close to the final product.
└── packer
├── builds
│ ├── app
│ │ ├── build.pkr.hcl
│ │ ├── hcp.pkr.hcl
│ │ ├── locals.pkr.hcl
│ │ ├── plugins.pkr.hcl
│ │ ├── source_aws.pkr.hcl
│ │ ├── source_azure.pkr.hcl
│ │ ├── source_gce.pkr.hcl
│ │ ├── variables_aws.pkr.hcl
│ │ ├── variables_azure.pkr.hcl
│ │ ├── variables_common.pkr.hcl
│ │ └── variables_hcp.pkr.hcl
│ └── base
│ ├── build.pkr.hcl
│ ├── locals.pkr.hcl
│ ├── plugins.pkr.hcl
│ ├── source_aws.pkr.hcl
│ ├── source_azure.pkr.hcl
│ ├── source_gce.pkr.hcl
│ ├── variables_aws.pkr.hcl
│ ├── variables_azure.pkr.hcl
│ ├── variables_common.pkr.hcl
│ └── variables_hcp.pkr.hcl
├── pkrvars
│ ├── os
│ │ ├── linux
│ │ │ ├── debian
│ │ │ │ ├── base.pkrvars.hcl
│ │ │ │ ├── nomad.pkrvars.hcl
│ │ │ │ ├── packer.pkrvars.hcl
│ │ │ │ ├── terraform.pkrvars.hcl
│ │ │ │ └── vault.pkrvars.hcl
│ │ │ └── rhel
│ │ └── windows
│ │ └── base.pkrvars.hcl
│ └── sources
│ └── sources.pkrvars.hcl
└── shared
├── README.MD
├── bootstrap
│ └── bootstrap_win.txt
├── files
├── playbooks
│ └── readme.md
└── scripts
├── debian
│ ├── base.sh
│ ├── deprovision-aws.sh
│ ├── deprovision-azure.sh
│ ├── deprovision-google.sh
│ ├── docker.sh
│ └── nomad.sh
├── rhel
└── windows
├── base.ps1
├── deprovision-aws.ps1
├── deprovision-azure.ps1
└── deprovision-google.ps1
Conclusion
In this article, I have shown how to create a multipurpose Packer template that can be used for various cloud providers and on-premise hosting solutions. By using dynamic blocks and variables, you can create a template that can be easily customized for different use cases.
FAQs
Q: What are the limitations of Packer?
A: Packer has limitations with meta-arguments, which can make it difficult to create complex templates.
Q: How do I create a multipurpose Packer template?
A: You can create a multipurpose Packer template by using dynamic blocks and variables to customize the template for different use cases.
Q: What is the best way to organize my Packer templates?
A: The best way to organize your Packer templates is to use a structured directory layout, such as the one shown in this article.
Q: Can I use Packer to create images for multiple cloud providers?
A: Yes, Packer can be used to create images for multiple cloud providers, such as AWS, Azure, and GCP.

