# Day 66 - Terraform Hands-on Project - Build Your Own AWS Infrastructure with Ease using Infrastructure as Code (Jan 31, 2024)

## **🙏 Introduction:**

In this blog, In the previous tasks, you have learned about the basics of Terraform, its configuration file, and creating an EC2 instance using Terraform. Today, we will explore more about Terraform and create multiple resources.

# **🎯Task: 1**

### **Create a VPC (Virtual Private Cloud) with CIDR block 10.0.0.0/16**

```plaintext
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

tags = {
    Name = "main"
  }
}
```

* This will create a new VPC in your AWS account with the specified CIDR block and a name tag of **main**.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704817632191/28006bd2-ab45-4c31-8335-73b1efbb1445.png?auto=compress,format&format=webp align="left")

* Run the **terraform init** command to initialize the working directory and download the required providers. After that, run **terraform apply** to create the VPC in our AWS account
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704818278949/80a74461-78ce-4053-b6eb-d65059b49d97.png?auto=compress,format&format=webp align="left")

* VPC has been created successfully
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704818392636/b5615d08-171d-40e4-8a55-46752fee8551.png?auto=compress,format&format=webp align="left")

### **Create a public subnet with CIDR block 10.0.1.0/24 in the above VPC**

```plaintext
resource "aws_subnet" "public_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"

  tags = {
    Name = "Public Subnet"
  }
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704818599839/d5e9b378-382b-48bd-a163-c60b81abd899.png?auto=compress,format&format=webp align="left")

* Run the **terraform init** command to initialize the working directory and download the required providers. After that, run **terraform apply** to create the public subnet in our AWS account
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704820415169/ecdef3ac-aecc-46fe-b8d6-13b90200e6a9.png?auto=compress,format&format=webp align="left")

* Public Subnet is created
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704820502735/a0772a10-5cde-47ae-8ce7-f419cb565be4.png?auto=compress,format&format=webp align="left")

### **Create a private subnet with CIDR block 10.0.2.0/24 in the above VPC**

```plaintext
resource "aws_subnet" "private_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.2.0/24"


  tags = {
    Name = "Private Subnet"
  }
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704820718201/6050ccc3-3a00-4998-b61a-913d38a6102c.png?auto=compress,format&format=webp align="left")

* Run the **terraform init** command to initialize the working directory and download the required providers. After that, run **terraform apply** to create the private subnet in our AWS account
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704820821420/13e81fef-8235-4c04-bdba-9e5664893c18.png?auto=compress,format&format=webp align="left")

* Private Subnet is created
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704820920714/ff55a7e8-f44b-4188-bfa7-a158e42c17e0.png?auto=compress,format&format=webp align="left")

### **Create an Internet Gateway (IGW) and attach it to the VPC**

```plaintext
resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw"
  }
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704821052398/8a77a105-62bf-467c-b0ce-2bf196e0db97.png?auto=compress,format&format=webp align="left")

* Run the **terraform init** command to initialize the working directory and download the required providers. After that, run **terraform apply** to create the Internet Gateway in our AWS account
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704821160689/c993a0f2-302b-4f30-bd42-9c51ca1ebd9a.png?auto=compress,format&format=webp align="left")

* Internet gateway is created
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704821248537/68be5024-bae8-487d-b996-9ed995f990d6.png?auto=compress,format&format=webp align="left")

* Internet Gateway (IGW) is attach it to the VPC
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704821367783/32122a5e-d279-4f96-89bd-68802dabaa38.png?auto=compress,format&format=webp align="left")

### **Create a route table for the public subnet and associate it with the public subnet. This route table should have a route to the Internet Gateway**

```plaintext
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

   route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }

   tags = {
    Name = "route-table"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public.id
}
```

* First we create a route table for public subnet.
    
* **aws\_route\_table** block creates a new route table in the VPC specified by vpc\_id attribute. It also defines a route that sends all traffic with destination CIDR 0.0.0.0/0 to the internet gateway specified by gateway\_id attribute. The tags attribute sets a name for the route table for easy identification.
    
* Then associate route table with public subnet.
    
* **aws\_route\_table\_association** block associates the newly created route table with a public subnet specified by the subnet\_id attribute. The route\_table\_id attribute refers to the ID of the route table created in the previous block.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704821939030/724703fe-f255-4b13-b3ec-7f06a2f46f7e.png?auto=compress,format&format=webp align="left")

* Run the **terraform init** command to initialize the working directory and download the required providers. After that, run **terraform apply** to create the route table in our AWS account
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704822045999/72853df4-8568-46c3-aae1-079035d2428f.png?auto=compress,format&format=webp align="left")

* Route table is successfully created
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704822112688/6c295ce0-073e-4158-adc6-e71bb53643a8.png?auto=compress,format&format=webp align="left")

* Route table is associate with public subnet
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704822233569/43888278-74e4-4df1-87ee-3b1dead284a6.png?auto=compress,format&format=webp align="left")

### **Launch an EC2 instance in the public subnet with the following details**

* AMI: ami-008fe2fc65df48dac
    
* Instance type: t2.micro
    
* Security group: Allow SSH access from anywhere
    
* User data: Use a shell script to install Apache and host a simple website
    
* Create an Elastic IP and associate it with the EC2 instance
    

```plaintext
resource "aws_instance" "web_server" {
  ami           = "ami-008fe2fc65df48dac"
  instance_type = "t2.micro"
  key_name      = "terra_key"
  subnet_id     = aws_subnet.public_subnet.id

  vpc_security_group_ids = [
      aws_security_group.ssh_access.id
  ]
}
resource "aws_security_group" "ssh_access" {
  name_prefix = "ssh_access"
  vpc_id      =  aws_vpc.main.id


  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
```

**User data: Use a shell script to install Apache and host a simple website**

```plaintext
 user_data = <<-EOF
        #!/bin/bash
        sudo apt-get update -y
        sudo apt-get install apache2 -y
        sudo systemctl start apache2
        sudo systemctl enable apache2
        echo "<html><body><h1>Welcome to my website!</h1></body></html>" > /var/www/html/index.html
        sudo systemctl restart apache2
  EOF
```

**Create an Elastic IP and associate it with the EC2 instance**

```plaintext
resource "aws_eip" "eip" {
  instance = aws_instance.web_server.id


  tags = {
    Name = "test-eip"
  }
}
```

Final [**main.tf**](https://sutish.hashnode.dev/day-66-terraform-hands-on-project-build-your-own-aws-infrastructure-with-ease-using-infrastructure-as-code-iac-techniquesinterview-questions#heading-task-1) file

```plaintext
terraform {
 required_providers {
        aws = {
        source  = "hashicorp/aws"
        version = "~> 4.16"
        }
    }
        required_version = ">= 1.2.0"
}

provider "aws" {
region = "us-west-2"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

tags = {
    Name = "main"
  }
}

resource "aws_subnet" "public_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"

  tags = {
    Name = "Public Subnet"
  }
}

resource "aws_subnet" "private_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.2.0/24"


  tags = {
    Name = "Private Subnet"
  }
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

   route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }

   tags = {
    Name = "route-table"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public.id
}

resource "aws_instance" "web_server" {
  ami           = "ami-008fe2fc65df48dac"
  instance_type = "t2.micro"
  key_name      = "terra_key"
  subnet_id     = aws_subnet.public_subnet.id

  vpc_security_group_ids = [
      aws_security_group.ssh_access.id
  ]

  user_data = <<-EOF
        #!/bin/bash
        sudo apt-get update -y
        sudo apt-get install apache2 -y
        sudo systemctl start apache2
        sudo systemctl enable apache2
        echo "<html><body><h1>Welcome to my website!</h1></body></html>" > /var/www/html/index.html
        sudo systemctl restart apache2
  EOF

    tags = {
    Name = "terraform-instance"
  } 
}
resource "aws_security_group" "ssh_access" {
  name_prefix = "ssh_access"
  vpc_id      =  aws_vpc.main.id


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

resource "aws_eip" "eip" {
  instance = aws_instance.web_server.id


  tags = {
    Name = "test-eip"
  }
}
```

* New instance is created with the desired details configuration
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704826547100/74cb4efd-44cc-4c49-8a3e-799f8b52229c.png?auto=compress,format&format=webp align="left")

* Elastic IP created
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704826642051/017768ae-ff20-4c1c-8add-150fc52aaba9.png?auto=compress,format&format=webp align="left")

### **Open the website URL in a browser to verify that the website is hosted successfully**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704826760139/bfbeecc3-02c9-4aea-a2fb-5b1f99ad160e.png?auto=compress,format&format=webp align="left")
