Deploying a Highly Available Web App on AWS Using Terraform

Today marked an exciting step in my Terraform 30-Day Challenge as I dove into Chapter 2 of "Terraform: Up & Running" by Yevgeniy Brikman. The focus was on variables and data sources, two powerful features that make Terraform configurations more dynamic and reusable.
What I Learned
1. Using Variables for Flexibility
Variables in Terraform allow us to parameterize our configurations, making them more adaptable. Instead of hardcoding values like region or instance_type, we can define them as variables and pass different values as needed.
In my implementation, I defined two variables in variables.tf:
variable "aws_region" {
description = "AWS region to deploy resources"
type = string
default = "us-west-2"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}
These variables were then referenced in the main configuration:
provider "aws" {
region = var.aws_region
}
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
# ... rest of the config
}
This makes it easy to change regions or instance types without modifying the core infrastructure code.
2. Leveraging Data Sources
Data sources allow Terraform to fetch external information (like the latest Amazon Linux AMI) and use it in configurations. Instead of hardcoding an AMI ID (which changes frequently), I used:
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
This dynamically retrieves the latest Amazon Linux 2 AMI, ensuring my EC2 instance always uses an up to date image.
3. Security Group & User Data Configuration
I also defined a security group to allow SSH (22), HTTP (80), and HTTPS (443) traffic:
resource "aws_security_group" "ec2_sg" {
name = "web-server-sg"
description = "Allow web traffic and SSH access"
# Ingress rules for SSH, HTTP, HTTPS
# Egress rule allowing all outbound traffic
}
Additionally, I used user_data to automatically install and configure an Apache web server upon instance launch:
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello World from Terraform 30 Day Challenge: Day 4</h1>" > /var/www/html/index.html
EOF
Results
After running terraform apply, my AWS infrastructure was successfully deployed:

A t2.micro EC2 instance running Amazon Linux 2
A security group allowing web and SSH access
An Apache web server serving a "Hello World" page

Key Takeaways
Variables make Terraform configurations reusable and flexible.
Data sources help fetch dynamic external data (like AMIs).
Security groups define inbound/outbound traffic rules.
User data automates instance initialization.
Looking forward to Day 5, where I’ll explore more advanced Terraform concepts




