Terraform Tutorial — Project 2: EC2 Web Server

1 minute read

Create an EC2 instance running a web server with a security group that allows HTTP and SSH traffic.


What You’ll Build

  • EC2 instance with Amazon Linux 2023
  • Security group allowing ports 22 (SSH) and 80 (HTTP)
  • User data script that installs and starts nginx
  • Outputs for the public IP and SSH command

Project Structure

project-2-ec2-webserver/
├── main.tf
├── variables.tf
└── outputs.tf

variables.tf

variable "region" {
  type    = string
  default = "us-east-1"
}

variable "instance_type" {
  type    = string
  default = "t3.micro"
}

variable "key_name" {
  type        = string
  description = "Name of the SSH key pair"
}

main.tf

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
}

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_security_group" "web" {
  name        = "web-server-sg"
  description = "Allow HTTP and SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow HTTP"
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow SSH"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    description = "Allow all outbound"
  }

  tags = {
    Name = "web-server-sg"
  }
}

resource "aws_instance" "web" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = var.instance_type
  key_name               = var.key_name
  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y nginx
    systemctl start nginx
    systemctl enable nginx
    echo "<h1>Hello from Terraform!</h1><p>Instance: $(hostname)</p>" > /usr/share/nginx/html/index.html
  EOF

  tags = {
    Name = "terraform-web-server"
  }
}

outputs.tf

output "public_ip" {
  value       = aws_instance.web.public_ip
  description = "Public IP of the web server"
}

output "web_url" {
  value       = "http://${aws_instance.web.public_ip}"
  description = "URL to access the web server"
}

output "ssh_command" {
  value       = "ssh -i ${var.key_name}.pem ec2-user@${aws_instance.web.public_ip}"
  description = "SSH command to connect"
}

Deploy

$ terraform init
$ terraform apply -var="key_name=my-key-pair"

# Test the web server
$ curl $(terraform output -raw web_url)

# Clean up
$ terraform destroy -var="key_name=my-key-pair"

← Project 1: S3 Static Website Project 3: VPC Network →