Golden AMIs with Packer and Ansible: Automated, Auditable Servers
How Packer and Ansible-local standardize EC2 provisioning on AWS, using SSM for secure builds and Parameter Store for centralized config, with a bonus disaster recovery win.
Manually provisioned EC2 instances tend to drift apart over time, becoming hard to audit and prone to human error. This piece describes a practical approach using Packer to orchestrate AMI builds while running Ansible in local mode inside the build instance itself, eliminating the need for external SSH connectivity and producing repeatable, versioned images. By configuring Packer's amazon-ebs builder to tunnel through AWS Session Manager instead of relying on traditional SSH, the build process avoids exposing port 22 or requiring public network routes, shrinking the attack surface during the most vulnerable phase of instance creation.
The key architectural decision is keeping application-specific configuration out of the image entirely. Packer and Ansible handle the structural layer—packages, hardening, service definitions—while environment-specific settings live in AWS Systems Manager Parameter Store as the single source of truth. A systemd service fetches these parameters on boot and applies them locally. This separation lets one golden AMI serve dev, UAT, and production alike, allows configuration changes without rebuilding images, and leverages Parameter Store's built-in change history for auditability.
An unplanned but valuable side effect is simplified disaster recovery: since the AMI is self-contained and configuration is decoupled and centrally stored, replicating the application to another AZ or region becomes purely an infrastructure task—copy the AMI, boot the instance, let config-sync pull the right settings. AZ failure simulations confirmed that the Packer-provisioned layer recovered far more predictably than components still dependent on manual steps.