All case studiesConfiguration Management

Terraform on AWS

A single EC2 instance defined entirely in code — no console clicks, no secrets in the repo, free-tier compliant, create and destroy on demand.

TerraformAWSInfrastructure as Code

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.

Terraform CLIinit · plan · applyCloud providerCLI profile authlookupcreateData sources (read-only)VM · network · firewallssh_commandoutput

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.

main.tfhcl
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}"
}
versions.tf + commandshcl
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 destroy

Outcome

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.

Have a similar challenge?

We deliver this work end to end — from first commit to a secure, live deploy. Let’s talk about yours.