How to deploy an infrastructure on AWS using Terraform?

Priyanshugoyal
5 min readSep 27, 2020

#TASK-1

About Terraform:

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can help with multi-cloud by having one workflow for all clouds. The infrastructure Terraform manages can be hosted on public clouds like Amazon Web Services, Microsoft Azure, and Google Cloud Platform, or on private clouds such as OpenStack, or Cloud Stack. Terraform treats infrastructure as code (IaC) so you never have to worry about your infrastructure drifting away from its desired configuration.

Before starting make sure that:

(i) Terraform and AWS CLI is installed on your system and the path of the terraform is set in environment variables.

(ii) Profile of the respective AWS user is configured.

Now, we will start writing the code in the following steps in the .tf file stored separately in a folder so that all the necessary data resides in one place:

Step by Step implementation:

  1. Specify the provider, create the key and security group which allow the port 80.
//Specifying the providerprovider "aws" {
region= "ap-south-1"
profile = "aws_user"
}
//launching a key pairresource "aws_key_pair" "mykey"{
key_name = "myawskey"
public_key ="your_public_key"
}
//launching a security groupresource "aws_security_group" "sg" {
name = "sg_for_task1"
description = "sg to allow port 80"
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"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

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

egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

2. Launch EC2 instance and use the key and security group which we have created in step 1.

//Launching an EC2 Instance with key-pair and security groups created above:resource "aws_instance"  "myinstance" {
ami = "ami-0447a12f28fddb066"
instance_type = "t2.micro"
key_name = "myawskey"
security_groups = ["sg_for_task1"]
connection {
type = "ssh"
user = "ec2-user"
private_key = file("C:/Users/priyanshu/Desktop/terraform/task1/myawskey.pem")
host = aws_instance.myinstance.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo yum install httpd php git -y",
"sudo systemctl restart httpd",
"sudo systemctl enable httpd",
]
}
tags = {
Name = "mynewos"
}
}

3. Launch one Volume (EBS) and mount that volume into /var/www/html

//Launching the EBSvolume in the same availability zone as that of the EC2 instanceresource "aws_ebs_volume" "myebs" {
availability_zone = aws_instance.myinstance.availability_zone
size = 1
tags = {
Name = "myebsvolume"
}
}
//Attaching EBS volume to the EC2 instance and also mounting the volume to /var/www/html
resource "aws_volume_attachment" "ebs_att" {
device_name = "/dev/sdh"
volume_id = "${aws_ebs_volume.myebs.id}"
instance_id = "${aws_instance.myinstance.id}"
force_detach = true
}
resource "null_resource" "nullremote" {
depends_on = [
aws_volume_attachment.ebs_att,
]
connection {
type = "ssh"
user = "ec2-user"
private_key = file("C:/Users/priyanshu/Desktop/terraform/task1/myawskey.pem")
host = aws_instance.myinstance.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo mkfs.ext4 /dev/xvdh",
"sudo mount /dev/xvdh /var/www/html",
"sudo rm -rf /var/www/html/*",
"sudo git clone https://github.com/priyanshu023/task1.git /var/www/html/"
]
}
}

4. Create S3 bucket.

//Creating a S3 bucketresource "aws_s3_bucket" "bucket" {
bucket = "terraform-bucket-001"
acl= "private"
provisioner "local-exec" {
command = "mkdir new1"
}
provisioner "local-exec" {
command = "git clone https://github.com/priyanshu023/task1images.git new1"
}
provisioner "local-exec" {
when = destroy
command = "rmdir/Q /S new1"
}


tags = {
name = "s3bucket"
}
}

5. Create a S3 bucket object which is publicly readable:

//Creating a S3 bucket object which is publically readable:resource "aws_s3_bucket_object" "object" {
depends_on = [
aws_s3_bucket.bucket,
]
acl = "public-read"
bucket = aws_s3_bucket.bucket.id
key = "terra.jpg"
source = "C:/Users/priyanshu/Downloads/task1.jpg"
content_type = "image/jpg"
}

locals {
s3_origin_id = "s3-${aws_s3_bucket.bucket.bucket}"
}

6. Create a Cloud front distribution with S3 as origin:

//creating a cloudfront distribution with S3 as originresource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = aws_s3_bucket.bucket.bucket_regional_domain_name
origin_id = "${local.s3_origin_id}"

custom_origin_config {
http_port= 80
https_port = 80
origin_protocol_policy="match-viewer"
origin_ssl_protocols = ["TLSv1","TLSv1.1","TLSv1.2"]
}
}
enabled = true
default_root_object = "task1.jpg"
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${local.s3_origin_id}"

forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}

restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}

connection {
type = "ssh"
user = "ec2-user"
private_key =
file("C:/Users/priyanshu/Desktop/terraform/task1/myawskey.pem")

host = aws_instance.myinstance.public_ip
}
//using the cloudfront URL to update the code in /var/www/html provisioner "remote-exec" {
inline = [
"sudo su << EOF",
"echo \"<img src='http://${aws_cloudfront_distribution.s3_distribution.domain_name}/${aws_s3_bucket_object.object.key}'>\" >> /var/www/html/index.html",
"EOF",
]
}
tags = {
Environment = "distribution"
}
}

7. Creating a null resource to execute the command to display webpage on local system.

//Creating a null resource to execute the command to display webpage on local system.
resource "null_resource" "nulllocal1" {
depends_on = [
aws_cloudfront_distribution.s3_distribution,
]
provisioner "local-exec" {
command = "chrome http://${aws_instance.myinstance.public_ip}"
}
}

Now, let’s first initialize this code using:

terraform init

Then, let’s run this code using:

terraform apply -auto-approve

Now, our webpage will automatically appear on the browser:

Now, we will destroy this whole infrastructure created using one command:

terraform destroy -auto-approve

Therefore, we have successfully completed our task 1.

Thank you for reading!!

--

--