AWS for DevOps — AMIs & Key Pairs
3.2 — AMIs & Key Pairs
An AMI (Amazon Machine Image) is a template that contains the OS, application server, and applications needed to launch an instance. Key pairs are the SSH credentials used to connect.
What Is an AMI?
Think of an AMI as a snapshot of a fully configured server. It includes:
- Operating system (Amazon Linux, Ubuntu, Windows, etc.)
- Pre-installed software
- Configuration files
- Data on attached storage volumes
AMI: custom-web-server-v1.2
┌──────────────────────────────────────┐
│ Amazon Linux 2023 │
│ + Nginx 1.24 │
│ + Node.js 20 LTS │
│ + CloudWatch Agent │
│ + /etc/nginx/nginx.conf (custom) │
│ + /opt/app/ (your application) │
└──────────────────────────────────────┘
│ │ │
▼ ▼ ▼
Instance 1 Instance 2 Instance 3
(identical) (identical) (identical)
Types of AMIs
| Source | Examples | Cost |
|---|---|---|
| AWS-provided | Amazon Linux, Ubuntu, Windows Server | Free (OS may have licence cost) |
| Marketplace | Pre-built appliances (firewalls, databases) | May have hourly software fee |
| Community | Shared by other users | Free, but use with caution |
| Custom (yours) | Your golden image | Storage cost for the snapshot |
Finding an AMI
# Find the latest Amazon Linux 2023 AMI
$ aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=al2023-ami-2023*-x86_64" \
"Name=state,Values=available" \
--query 'sort_by(Images,&CreationDate)[-1].[ImageId,Name]' \
--output text
ami-0abcdef1234567890 al2023-ami-2023.4.20260328.0-kernel-6.1-x86_64
# Find the latest Ubuntu 22.04 AMI
$ aws ec2 describe-images \
--owners 099720109477 \
--filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" \
"Name=state,Values=available" \
--query 'sort_by(Images,&CreationDate)[-1].[ImageId,Name]' \
--output text
ami-0xyz987654321abcde ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-20260325
Creating a Custom AMI
The golden image workflow:
- Launch a base instance
- Install and configure your software
- Create an AMI from the running (or stopped) instance
- Use the AMI to launch identical instances
# Step 1 — Launch and configure a base instance
$ aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key-pair
# Step 2 — SSH in and configure
$ ssh -i my-key-pair.pem ec2-user@<public-ip>
$ sudo yum install -y nginx nodejs
$ sudo systemctl enable nginx
$ exit
# Step 3 — Create the AMI
$ aws ec2 create-image \
--instance-id i-0abc123def456 \
--name "web-server-v1.0-$(date +%Y%m%d)" \
--description "Nginx + Node.js on Amazon Linux 2023" \
--no-reboot
{
"ImageId": "ami-0custom123456"
}
# Step 4 — Wait for it to be available
$ aws ec2 describe-images --image-ids ami-0custom123456 \
--query 'Images[0].State'
"available"
# Step 5 — Launch new instances from the custom AMI
$ aws ec2 run-instances \
--image-id ami-0custom123456 \
--instance-type t3.medium \
--count 3
--no-reboot: Creates the AMI without stopping the instance. The file system may not be perfectly consistent. For production golden images, stop the instance first.
AMI Lifecycle Management
Over time, you accumulate many AMIs. Clean up old ones:
# List your custom AMIs
$ aws ec2 describe-images --owners self \
--query 'Images[*].[ImageId,Name,CreationDate]' \
--output table
# Deregister an old AMI
$ aws ec2 deregister-image --image-id ami-0old123456
# Delete the associated snapshot (AMI doesn't auto-delete it)
$ aws ec2 describe-snapshots --owner-ids self \
--filters "Name=description,Values=*ami-0old123456*" \
--query 'Snapshots[*].SnapshotId'
["snap-0abc123"]
$ aws ec2 delete-snapshot --snapshot-id snap-0abc123
Key Pairs
A key pair consists of a public key (stored by AWS) and a private key (you download once). AWS uses the public key to encrypt a login challenge, and your private key decrypts it.
# Create a key pair
$ aws ec2 create-key-pair \
--key-name devops-key \
--key-type ed25519 \
--query 'KeyMaterial' \
--output text > devops-key.pem
# Set permissions (SSH refuses keys with open permissions)
$ chmod 400 devops-key.pem
# Use it to connect
$ ssh -i devops-key.pem ec2-user@<public-ip>
| Key Type | Security | Speed |
|---|---|---|
| RSA (2048-bit) | Good | Slower |
| ED25519 | Better | Faster |
Recommendation: Use ED25519 for new key pairs. It is more secure and generates smaller keys.
Key Pair Best Practices
| Practice | Why |
|---|---|
| One key pair per environment | Limit blast radius if a key leaks |
| Store private keys in a secrets manager | Not in Git, not on laptops |
| Use SSM Session Manager instead of SSH | No keys needed, full audit trail |
| Rotate keys periodically | Reduce window of compromise |
| Never share private keys between team members | Use IAM users or SSM for individual access |
Common Mistakes
| Mistake | Why It Hurts | Fix |
|---|---|---|
| Not deregistering old AMIs | Paying for snapshot storage | Automate AMI lifecycle |
| Using community AMIs blindly | Could contain malware | Stick to AWS or Marketplace AMIs |
| Losing the private key | Locked out of instances | Use SSM Session Manager as backup |
| Creating AMIs from running instances with active writes | Inconsistent file system | Stop the instance first or use --no-reboot with caution |
Quick Reference
| Task | Command |
|---|---|
| Find latest Amazon Linux AMI | aws ec2 describe-images --owners amazon --filters "Name=name,Values=al2023-*" |
| Create custom AMI | aws ec2 create-image --instance-id ID --name NAME |
| List your AMIs | aws ec2 describe-images --owners self |
| Deregister AMI | aws ec2 deregister-image --image-id AMI_ID |
| Create key pair | aws ec2 create-key-pair --key-name NAME --key-type ed25519 |
| List key pairs | aws ec2 describe-key-pairs |
| Delete key pair | aws ec2 delete-key-pair --key-name NAME |
Next → Security Groups