Compute
Deploy an Apache Web Server on AWS EC2 Using Terraform

Deploy an Apache Web Server on AWS EC2 Using Terraform

Written by Kenechi Dukor (opens in a new tab)

If you already know how to launch an EC2 instance manually, Terraform helps you do the same thing using code. Instead of clicking around the AWS console, you describe what you want and Terraform creates it for you.

In this guide, you will use Terraform to:

  • Create an EC2 instance
  • Allow web and SSH traffic
  • Install Apache automatically
  • Access the web server from a browser

This is a common starting point when learning Infrastructure as Code.

What You Need Before You Start

Make sure you have the following ready:

  • Terraform installed
  • AWS CLI installed and authenticated
  • An existing VPC and subnet
  • An existing EC2 key pair in AWS

Terraform will reference the key pair by name. It does not create one in this setup.

Step 1: Set Up the Project Folder

Create a new folder and add these files:

terraform-ec2-apache/
├── main.tf
├── variables.tf
├── outputs.tf
└── user_data.sh

Each file has a single purpose. This keeps things easy to follow.

Step 2: Define Inputs with Variables

The variables.tf file holds values you may want to change later, such as region or instance type.

variable "aws_region" {
  type    = string
  default = "us-west-2"
}
 
variable "instance_type" {
  type    = string
  default = "t2.micro"
}
 
variable "key_name" {
  type = string
}
 
variable "vpc_id" {
  type = string
}
 
variable "subnet_id" {
  type = string
}

You will pass key_name, vpc_id, and subnet_id when running Terraform.

Step 3: Add a Startup Script for Apache

The user_data.sh file runs when the EC2 instance starts. It installs and starts Apache without manual setup.

#!/bin/bash
 
yum update -y
yum install -y httpd
 
systemctl start httpd
systemctl enable httpd
 
echo "<h1>Hello from Terraform</h1>" > /var/www/html/index.html

This is how the server becomes usable immediately after launch.

Step 4: Define the Infrastructure

All AWS resources are defined in main.tf.

AWS Provider

provider "aws" {
  region = var.aws_region
}

Security Group

This allows HTTP traffic for the website and SSH for access.

resource "aws_security_group" "web_sg" {
  vpc_id = var.vpc_id
 
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
 
  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"]
  }
}

Get the Amazon Linux AMI

Terraform fetches the latest Amazon Linux 2 image automatically.

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
 
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

EC2 Instance

resource "aws_instance" "web" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = var.instance_type
  key_name               = var.key_name
  subnet_id              = var.subnet_id
  vpc_security_group_ids = [aws_security_group.web_sg.id]
 
  user_data = file("user_data.sh")
 
  tags = {
    Name = "terraform-apache"
  }
}

At this point, Terraform knows how to create the server.

Step 5: Expose the Result

The outputs.tf file prints useful information after deployment.

output "public_ip" {
  value = aws_instance.web.public_ip
}
 
output "web_url" {
  value = "http://${aws_instance.web.public_dns}"
}

Step 6: Deploy with Terraform

Run the following commands in order:

terraform init
terraform plan \
  -var="key_name=your-key-name" \
  -var="vpc_id=your-vpc-id" \
  -var="subnet_id=your-subnet-id"
terraform apply \
  -var="key_name=your-key-name" \
  -var="vpc_id=your-vpc-id" \
  -var="subnet_id=your-subnet-id"

Type yes when prompted.

Step 7: Access the Web Server

Once Terraform finishes, copy the web_url output and open it in a browser.

You should see the Apache page created in the startup script.

Step 8: Cleaning Up

When you no longer need the resources:

terraform destroy \
  -var="key_name=your-key-name" \
  -var="vpc_id=your-vpc-id" \
  -var="subnet_id=your-subnet-id"

Terraform removes everything it created.

Wrap Up

This walkthrough shows how Terraform replaces manual EC2 setup with a repeatable workflow. The same pattern works for APIs, internal tools, and test environments.

From here, you can:

  • Add HTTPS
  • Pull application code in user_data.sh
  • Convert this into a reusable Terraform module
  • Introduce remote state and environments