How to Provision an AWS EC2 Instance with Terraform

An EC2 instance in Terraform is the aws_instance resource - it just needs a real AMI id and a valid instance type. The two things that break apply are a placeholder AMI and a bad instance-type name. Here's how to get both right.

DevOps Engineerawsec2terraform

The resource

resource "aws_instance" "web" {
  ami           = "ami-0abcdef1234567890"   # a REAL ami id for your region
  instance_type = "t3.micro"                # a valid type
  tags = { Name = "web" }
}

Two fields do all the work - and both are where applies fail.

Don't hard-code a placeholder AMI

AMI ids are region-specific and change over time, so ami-deadbeef or a copied id from a tutorial will fail. Look up a current one with a data source instead of pasting:

data "aws_ami" "al2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.al2023.id    # always a valid, current id
  instance_type = "t3.micro"
}

Use a valid instance type

Instance types follow family + size: t3.micro, t3.small, m5.large. A bad suffix like t2.nano-x isn't a real type and errors on apply. When unsure, t3.micro is a safe, cheap default.

Apply

terraform init
terraform plan      # see exactly what will be created
terraform apply -auto-approve

How to debug

Look up the AMI instead of hard-coding it

A hard-coded AMI id rots: it is region-specific and gets deprecated. Resolve the latest one at plan time with a data source:

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

Then reference ami = data.aws_ami.ubuntu.id. Beyond the AMI and instance type, a usable instance needs key_name for SSH access, vpc_security_group_ids to control traffic, subnet_id to place it, and tags so you can find and bill it. Use user_data to run a bootstrap script on first boot. Together these turn a bare instance into one you can actually reach and manage.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I create an EC2 instance with Terraform?

Use the aws_instance resource with a valid ami and instance_type, then terraform init and terraform apply. Look the AMI up with an aws_ami data source rather than hard-coding it.

Why does Terraform say InvalidAMIID?

The AMI id is a placeholder or from another region - AMI ids are region-specific. Use an aws_ami data source (most_recent + a name filter) so Terraform resolves a current, valid id automatically.

What's a valid EC2 instance_type?

family.size, e.g. t3.micro, t3.small, m5.large. Invalid suffixes like t2.nano-x fail on apply. t3.micro is a safe cheap default.

Keep learning

Fix the Nginx 502 Bad GatewayDevOps projectRecover a Crashed Linux ServiceDevOps projectCorrect a Postgres Port MismatchDevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →