The challenge
Clicking a VM together in the AWS console is fast the first time and a liability forever after — nobody can reproduce it, review it, or tear it down cleanly, and it is far too easy to leave credentials lying around.
Our approach
We declare the whole instance in Terraform and let read-only data sources look up the latest AMI, the default VPC, and its subnets — so nothing is hardcoded. Authentication uses a named AWS CLI profile; no access keys ever touch the repository. The configuration outputs a ready-to-run SSH command and feeds cleanly into downstream Ansible and Jenkins.
Technical specifics
- Terraform ≥ 1.5.0 with the AWS provider pinned to ~> 5.0.
- A t3.micro instance (smallest free-tier-eligible x86_64 type) on the latest Amazon Linux 2023.
- 8 GiB gp3 root volume, within the 30 GiB EBS free-tier allowance.
- A security group opening SSH (22), HTTP (80), and HTTPS (443); default region us-west-2.
- Three resources and three read-only data lookups — no count or for_each — kept deliberately simple.
Example configuration
Data sources resolve the AMI and network at plan time; a handful of resources create the instance; an output hands you the SSH command.
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter { name = "name"; values = ["al2023-ami-2023.*-x86_64"] }
}
resource "aws_instance" "web" {
ami = data.aws_ami.al2023.id
instance_type = "t3.micro" # free-tier eligible
vpc_security_group_ids = [aws_security_group.web.id]
root_block_device { volume_size = 8; volume_type = "gp3" }
tags = { Name = var.name }
}
output "ssh_command" {
value = "ssh ec2-user@${aws_instance.web.public_ip}"
}terraform {
required_version = ">= 1.5.0"
required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } }
}
provider "aws" { region = var.region; profile = "freetier" } # no keys in repo
# terraform init && terraform plan && terraform apply
# terraform output ssh_command
# terraform destroyOutcome
Reproducible, reviewable single-VM provisioning with zero secrets in version control, declarative diffs before every change, and on-demand teardown — all within the AWS free tier.