Create EC2 Instance with Dynamic AMI ID
Query AWS programmatically for the latest Amazon Linux AMI using Terraform data sources. Automatically attach custom local SSH key pairs, security group firewall rules, and expose the EC2 public IP dynamically.
Core Implementation Highlights
The Complete Terraform Code
Save the code below into main.tf. It dynamically fetches the newest Amazon Linux AMI, creates an SSH Key Pair from your public key, provisions a Security Group for SSH access, creates a t2.micro EC2 instance, and outputs its public IP address.
# Query AWS for the latest Amazon Linux AMI (Dynamic AMI ID)
data "aws_ami" "amazonlinux" {
most_recent = true
owners = ["137112412989"]
filter {
name = "architecture"
values = ["x86_64"]
}
}
# Register local SSH public key with AWS
resource "aws_key_pair" "shankey" {
key_name = "serverkey"
public_key = file("/home/ak/.ssh/id_rsa.pub")
}
# Security Group Firewall allowing SSH (Port 22) Ingress & All Egress
resource "aws_security_group" "webserver_ig" {
name = "webserver_ig"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Provision EC2 Instance using Dynamic AMI ID
resource "aws_instance" "webserver" {
ami = data.aws_ami.amazonlinux.id
instance_type = "t2.micro"
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.webserver_ig.id]
key_name = aws_key_pair.shankey.key_name
}
# Output the assigned public IP address of the server
output "aws_ec2_name" {
value = aws_instance.webserver.public_ip
}Resource-by-Resource Explanation
data "aws_ami" "amazonlinux"
Instead of hardcoding a static AMI ID (which changes by region and gets outdated), Terraform queries the AWS API dynamically at runtime to fetch the latest official Amazon Linux image.
most_recent = true: Selects the newest image matching filters.owners = ["137112412989"]: Amazon's official AWS account ID for official AMIs.filter { name = "architecture" values = ["x86_64"] }: Narrows down query to 64-bit x86 hardware.
data "aws_ami" "amazonlinux" {
most_recent = true
owners = ["137112412989"]
filter {
name = "architecture"
values = ["x86_64"]
}
}aws_key_pair.shankey
Registers your local SSH public key with AWS under the name serverkey. The built-in file() function reads your public key from disk at /home/ak/.ssh/id_rsa.pub.
resource "aws_key_pair" "shankey" {
key_name = "serverkey"
public_key = file("/home/ak/.ssh/id_rsa.pub")
}aws_security_group.webserver_ig
Acts as a virtual firewall for your EC2 server:
- Ingress: Allows SSH connection over TCP port
22from any IP address (0.0.0.0/0). - Egress: Allows all outbound traffic (protocol
-1) to any destination so your instance can update packages and reach the internet.
resource "aws_security_group" "webserver_ig" {
name = "webserver_ig"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}aws_instance.webserver
Provisions the EC2 virtual machine linking the dynamic AMI ID, SSH Key, and Security Group:
ami = data.aws_ami.amazonlinux.id: Injects the dynamic AMI ID returned by the data source.instance_type = "t2.micro": Selects AWS Free-Tier eligible instance sizing.associate_public_ip_address = true: Requests a public IPv4 address.vpc_security_group_ids&key_name: Binds the security group and SSH key created above.
resource "aws_instance" "webserver" {
ami = data.aws_ami.amazonlinux.id
instance_type = "t2.micro"
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.webserver_ig.id]
key_name = aws_key_pair.shankey.key_name
}output "aws_ec2_name"
Prints the newly assigned public IP address directly in your terminal output after applying the configuration, allowing you to instantly SSH into the instance with ssh -i ~/.ssh/id_rsa ec2-user@<PUBLIC_IP>.
output "aws_ec2_name" {
value = aws_instance.webserver.public_ip
}Deployment & Execution Commands
Run the standard Terraform lifecycle commands to validate, plan, and apply your dynamic infrastructure:
# 1. Initialize AWS Provider plugins
$ terraform init
# 2. Format and validate configuration syntax
$ terraform fmt
$ terraform validate
# 3. Preview execution plan (fetches dynamic AMI)
$ terraform plan
# 4. Provision infrastructure in AWS
$ terraform apply -auto-approve
# 5. SSH into your new server
$ ssh -i ~/.ssh/id_rsa ec2-user@$(terraform output -raw aws_ec2_name)
# 6. Clean up resources when finished
$ terraform destroy -auto-approve