Packer Components
Packer components build machine images (AMIs, VM images, container images) using HashiCorp Packer. They allow you to manage image builds with the same stack-based configuration approach used for Terraform and Helmfile.
Available Configuration Sections
Packer components support the common configuration sections:
vars- Variables passed to packer.
env- Environment variables during execution.
settings- Integrations and metadata.
metadata- Component behavior and inheritance.
command- Override packer binary.
hooks- Lifecycle event handlers.
Component Structure
A typical Packer component configuration:
components:
packer:
ami-ubuntu:
metadata:
component: ami-ubuntu
vars:
region: us-east-1
instance_type: t3.medium
source_ami_filter:
name: "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
owner: "099720109477" # Canonical
ami_name_prefix: "acme-ubuntu"
env:
AWS_PROFILE: acme-prod
Packer Directory Structure
Packer components are located in the path configured in atmos.yaml:
# atmos.yaml
components:
packer:
base_path: components/packer
Example structure:
components/packer/
├── ami-ubuntu/
│ ├── template.pkr.hcl
│ ├── variables.pkr.hcl
│ └── scripts/
│ ├── setup.sh
│ └── cleanup.sh
├── ami-eks-node/
│ ├── template.pkr.hcl
│ └── variables.pkr.hcl
└── docker-base/
└── template.pkr.hcl
Packer Template
Each Packer component contains HCL templates that use variables passed from Atmos:
Component-Type Defaults
Define defaults for all Packer components:
# Apply to all Packer components
packer:
vars:
region: us-east-1
tags:
ManagedBy: Atmos
Builder: Packer
env:
PACKER_LOG: "1"
AWS_PROFILE: acme-build
# Individual components
components:
packer:
ami-ubuntu:
vars:
instance_type: t3.medium
Complete Example
Template Configuration
Atmos supports two ways to specify Packer templates:
Directory Mode (Default)
By default, Atmos passes the component directory to Packer, which automatically loads all *.pkr.hcl files.
This is the recommended approach for organizing Packer configurations:
components:
packer:
my-ami:
# No settings.packer.template - uses directory mode
# Packer loads all *.pkr.hcl files from the component directory
vars:
region: us-east-1
This allows you to organize your Packer component with multiple files:
components/packer/my-ami/
├── variables.pkr.hcl # Variable declarations
├── main.pkr.hcl # Source and build blocks
├── locals.pkr.hcl # Local values (optional)
└── plugins.pkr.hcl # Required plugins (optional)
Single File Mode
For simple components or when you need to specify a particular template file:
components:
packer:
my-ami:
settings:
packer:
template: main.pkr.hcl # Use specific file
vars:
region: us-east-1
You can also use the --template (or -t) flag on the command line to override the template:
atmos packer validate my-ami -s prod --template main.pkr.hcl
Directory mode is recommended because it:
- Follows Packer best practices for organizing configurations
- Allows separation of variables, sources, and builds into logical files
- Simplifies stack manifests by not requiring explicit template configuration
Running Packer Commands
Atmos provides commands that wrap Packer operations:
# Initialize Packer plugins
atmos packer init ami-ubuntu -s plat-ue1-prod
# Validate templates
atmos packer validate ami-ubuntu -s plat-ue1-prod
# Build images
atmos packer build ami-ubuntu -s plat-ue1-prod
# Run any packer subcommand
atmos packer <subcommand> <component> -s <stack>
Environment Variables
Common environment variables for Packer components:
PACKER_LOG- Enable logging (set to
1). PACKER_LOG_PATH- Path to log file.
AWS_PROFILE- AWS profile for authentication.
AWS_REGION- Default AWS region.
PACKER_CACHE_DIR- Directory for Packer cache.
Variables File Generation
Atmos generates a variables file that Packer uses during builds:
// atmos-packer.pkrvars.json (auto-generated)
{
"region": "us-east-1",
"instance_type": "t3.medium",
"ami_name_prefix": "acme-prod",
"source_ami_filter": {
"name": "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*",
"owner": "099720109477"
},
"tags": {
"Environment": "prod",
"ManagedBy": "Atmos"
}
}
Passing Secrets Securely
The generated variables file is written to disk in plaintext (world‑readable, 0644) so Packer
can read it. Unlike Terraform — which keeps secret‑bearing vars off disk — Packer performs no
off‑disk partitioning. Never put secrets in a Packer component's vars section.
env, not varsValues in the env section are injected only into the Packer subprocess environment and are
never written to the variables file. Declare secrets under
secrets.vars, reference them with
!secret in env, and read them in the Packer template with the
env function.
Read the secret from the environment in the Packer template (Packer's env function is allowed in
variable defaults and locals):
Multi-Cloud Support
Packer components can build images for multiple cloud providers:
AWS AMI
components:
packer:
ami-builder:
vars:
region: us-east-1
source_ami_filter:
name: "ubuntu/images/*"
owner: "099720109477"
Azure VM Image
components:
packer:
azure-image:
vars:
azure_subscription_id: "{{ env \"ARM_SUBSCRIPTION_ID\" }}"
azure_resource_group: "packer-images-rg"
azure_location: "eastus"
env:
ARM_CLIENT_ID: "{{ env \"ARM_CLIENT_ID\" }}"
ARM_CLIENT_SECRET: "{{ env \"ARM_CLIENT_SECRET\" }}"
GCP Machine Image
components:
packer:
gcp-image:
vars:
project_id: "my-gcp-project"
zone: "us-central1-a"
source_image_family: "ubuntu-2204-lts"
env:
GOOGLE_APPLICATION_CREDENTIALS: "/path/to/credentials.json"
Docker Image
components:
packer:
docker-image:
vars:
repository: "myregistry/myimage"
tag: "latest"
base_image: "ubuntu:22.04"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
Best Practices
-
Version Pin Plugins: Always specify explicit plugin versions in your Packer templates.
-
Use Source AMI Filters: Use filters with
most_recent = trueto automatically get the latest base images. -
Tag Everything: Apply consistent tags to all built images for tracking and cost allocation.
-
Use Provisioner Scripts: Keep provisioning logic in external scripts for easier testing and maintenance.
-
Clean Up: Include cleanup scripts to reduce image size and remove sensitive data.
-
Use Dependencies: Define
depends_onwhen images need to be built in a specific order. -
Centralize Defaults: Define common settings in catalog defaults and override only when necessary.