You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
This final lesson brings together everything you have learned about EC2 by diving into Launch Templates — the modern way to define instance configurations — and a comprehensive set of best practices for running EC2 in production.
A Launch Template is a versioned configuration resource that specifies all the parameters needed to launch an EC2 instance. It replaces the older Launch Configuration and is the recommended approach for all new deployments.
| Feature | Launch Template | Launch Configuration |
|---|---|---|
| Versioning | Yes — multiple versions per template | No — immutable, must create new |
| Modification | Create new version; keep old | Must create new LC |
| Mixed instances | Supports mixed instance types | Single instance type only |
| Spot options | Full Spot configuration | Limited |
| Network interfaces | Full ENI configuration | Limited |
| Source for ASG | Yes | Yes (legacy) |
| Source for EC2 Fleet | Yes | No |
| Default version | Configurable ($Latest or $Default) | N/A |
| Partial parameters | Yes — override at launch time | Must specify all parameters |
| T2/T3 credit spec | Configurable | Not configurable |
Always use Launch Templates for new deployments. Launch Configurations are legacy and may not support future EC2 features.
aws ec2 create-launch-template \
--launch-template-name production-web-server \
--version-description "v1 - Amazon Linux 2023, t3.medium, gp3" \
--launch-template-data '{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "t3.medium",
"KeyName": "prod-key",
"SecurityGroupIds": ["sg-web-0123456789"],
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 20,
"VolumeType": "gp3",
"Iops": 3000,
"Throughput": 125,
"Encrypted": true,
"DeleteOnTermination": true
}
}
],
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{"Key": "Environment", "Value": "production"},
{"Key": "Team", "Value": "platform"}
]
},
{
"ResourceType": "volume",
"Tags": [
{"Key": "Environment", "Value": "production"}
]
}
],
"MetadataOptions": {
"HttpTokens": "required",
"HttpEndpoint": "enabled",
"HttpPutResponseHopLimit": 1
},
"Monitoring": {
"Enabled": true
},
"UserData": "'$(base64 -w0 <<'USERDATA'
#!/bin/bash
set -euxo pipefail
yum update -y
yum install -y amazon-cloudwatch-agent
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a start
USERDATA
)'"
}'
# Create a new version with an updated AMI
aws ec2 create-launch-template-version \
--launch-template-name production-web-server \
--version-description "v2 - Updated AMI with March patches" \
--source-version 1 \
--launch-template-data '{
"ImageId": "ami-0newami1234567890"
}'
# Set the default version
aws ec2 modify-launch-template \
--launch-template-name production-web-server \
--default-version 2
# List versions
aws ec2 describe-launch-template-versions \
--launch-template-name production-web-server
When used with an Auto Scaling Group, you can reference $Latest or $Default version. Then, trigger an Instance Refresh to rolling-replace instances with the new version.
The UserData field lets you run a script when the instance first boots. Common uses:
#!/bin/bash
set -euxo pipefail
# Update packages
yum update -y
# Install application dependencies
yum install -y nodejs npm
# Pull application code
aws s3 cp s3://my-app-bucket/releases/latest.tar.gz /opt/app/
tar -xzf /opt/app/latest.tar.gz -C /opt/app/
# Start the application
cd /opt/app
npm install --production
pm2 start server.js --name my-app
# Signal CloudFormation or the ASG that the instance is ready
/opt/aws/bin/cfn-signal -e $? --stack my-stack --resource MyASG --region us-east-1
Best practice: Keep user data scripts short and idempotent. For complex configuration, use configuration management tools (Ansible, Chef, Puppet) or bake everything into the AMI.
| Practice | Details |
|---|---|
| Use IMDSv2 | Require token-based access to instance metadata (HttpTokens: required); prevents SSRF attacks from retrieving credentials |
| Use IAM roles, not credentials | Attach an instance profile with an IAM role instead of storing access keys on the instance |
| Minimise security group rules | Follow least privilege — only open required ports to required sources |
| Prefer Session Manager over SSH | No need to open port 22; all sessions are logged and auditable |
| Encrypt all EBS volumes | Enable account-level default encryption |
| Patch regularly | Use AWS Systems Manager Patch Manager for automated patching |
| Disable root login | Use named user accounts with sudo |
| Enable detailed monitoring | 1-minute CloudWatch metrics (vs. default 5-minute) |
The Instance Metadata Service provides information about the instance (IP addresses, IAM role credentials, user data) at http://169.254.169.254. IMDSv2 adds a security layer by requiring a token:
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.