Source: Dev.to | Dec 23, 2025 (UTC)
Introduction:
In IT operations,Imagine We’re working in a cloud organization that deploys hundreds of EC2 instances every month. Each instance needs to be secure, compliant.Manually configuring each instance is a nightmare. Instead, you want a golden image — a reusable AMI that’s pre-hardened and provisioned with all necessary tools.
This is the point at which Packer becomes relevant.
Problem Statement:
In most organizations, EC2 instances are launched frequently to support various workloads. But here’s the catch — each instance needs to be:
Secure and compliant
Equipped with monitoring and security agents
Consistently configured
Real Time Scenario:
Suppose you’re part of a security-conscious enterprise. Every EC2 instance must:
-
Follow CIS benchmarks
-
Have CrowdStrike and Qualys agents installed
Instead of configuring each instance post-launch, you want to create a golden AMI that’s already hardened and provisioned. This image will serve as the base for all future deployments — saving time and ensuring consistency.
Tools Involved:
- Packer
- AWS EC2
- Ansible
- Gitlab CI/CD
- Amazon SSM
Architecture Diagram:
This workflow automates the creation of a secure AMI by:
Launching a temporary EC2 instance from a base image.
Running provisioning scripts to:
Apply OS hardening (CIS benchmarks, firewall rules, SSH configs).
Creating a new AMI from the configured instance.
Terminating the temporary instance.
Implementation Steps :
Step1: Install Packer
Step2: Create Packer Template with Ansible Provisioning
This Packer template automates the creation of a custom Amazon Machine Image (AMI) by launching a temporary EC2 instance in a specific AWS VPC and subnet, using a designated SSH key pair for secure access.
Code block
packer { required_plugins { amazon = { version = ">= 1.2.8" source = "github.com/hashicorp/amazon" } ansible = { version = "~> 1" source = "github.com/hashicorp/ansible" } } } variable "ami_prefix" { type = string default = "" } variable "reference_image" { type = string default = "" } locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") } variable "privatekey"{ type = string default = "" } source "amazon-ebs" "amazon_linux" { ami_name = "${var.ami_prefix}-${local.timestamp}" instance_type = "t2.micro" region = "ap-south-1" vpc_id = "vpc-07b2ce11f9b189f3b" subnet_id = "subnet-063ebc661edd9fb37" security_group_id = "sg-04e9ae673095b02e9" ssh_interface = "private_ip" associate_public_ip_address = true ssh_keypair_name = "runner_key" ssh_private_key_file = var.privatekey source_ami_filter { filters = { name = "${var.reference_image}" root-device-type = "ebs" virtualization-type = "hvm" } most_recent = true owners = [""] } ssh_username = "ec2-user" } build { name = "learn-packer" sources = [ "source.amazon-ebs.amazon_linux" ] provisioner "shell" { inline = [ "sleep 20", "echo '--- Running AMI pre-check ---'", "set -e", "sudo mkdir -p /usr/lib", "# Ensure SFTP subsystem path exists", "if [ ! -f /usr/lib/sftp-server ]; then", " if [ -f /usr/libexec/openssh/sftp-server ]; then", " sudo ln -s /usr/libexec/openssh/sftp-server /usr/lib/sftp-server", " echo 'Linked /usr/libexec/openssh/sftp-server -> /usr/lib/sftp-server';", " else", " echo 'Warning: sftp-server not found, installing openssh-server...';", " sudo yum install -y openssh-server || sudo apt-get install -y openssh-server;", " fi;", "fi", "# Basic network sanity check", "sudo yum clean all || true", "sudo yum update -y || true", "echo '--- Pre-check complete ---'" ] } provisioner "shell" { inline = [ "sudo mkdir -p /tmp/.ansible", "sudo chmod 777 /tmp/.ansible" ] } provisioner "ansible" { playbook_file = "./playbook/main.yml" use_proxy = false extra_arguments = ["--vault-password-file=/home/gitlab-runner/.vault_pass", "-e", "ansible_remote_tmp=/tmp/.ansible", "-e", "ansible_local_tmp=/tmp/.ansible", "-e", "ansible_scp_if_ssh=True", "-e", "ansible_python_interpreter=/usr/bin/python3", "-e", "ansible_ssh_transfer_method=scp"] } }
Enter fullscreen mode
Exit fullscreen mode




Залишити відповідь