Network For Web Portal Using Terraform And Aws

Gupta Aditya
7 min readJan 15, 2023

Hey guys hope you all are doing good in today’s article we are going to see how to create our VPC, Subnet, Internet Gateway, Routing Table and Nat Gateway.

Let’s get started here I am taking one real-life example and deploying the above things we generally host or create WordPress site and for that, we have to set database setup and we want database won’t accessible from outside from world so that our data can be safe because the main thing is our data it should be leaked we all know how sensitive database is but for upgrading or some other work we might want to access DB but we if we give public Ip then it can be hacked and database is in risk so for that, we use Bastion Host this is a device only through which our DB can communicate and we can manage the things in DB and also we want DB contact to the internet like it can go to internet and download packages but no one from the internet can come in so For we use Nat gateway and this is the difference between Nat gateway and Internet Gateway.

Guys, here I consider you have basic knowledge of AWS and terraform installed today we are going to use terraform for this setup. If you have not read my previous article on Aws and terraform I would suggest reading it here in LINK.

Let’s get started with deployment thing so first of all, make a new folder of whichever name you want and then make a new file with any name but the extension should be .tf.

You can also clone git repo I provide at the end of the article.

Once the file is created open it and apply the following code

provider “aws” {

region = “ap-south-1”

}

Guys for the above code you aws profile should be configured in your system via aws cli.

Once this is done we are going to launch a vpc and two subnet one public Subnet and one private subnet.

Public subnet is used for WordPress which is used for front end services.

Public subnet is used For storing databases and it is only be managed from bastion host and not from the outside world.

Here public subnet will have public IP so that people can access our site but for the private subnet, there will only be private IP so you might be thinking if we don’t have public IP then how can we do ssh to the instance which is an associate with private subnet so guys subnet within one vpc have internal connectivity the can communicate with each other but they should be under the same VPC.

To Launch the Vpc and Subnet write the following code

resource “aws_vpc” “terra” {

cidr_block = “192.168.0.0/16”

instance_tenancy = “default”

tags = {

Name = “terra”

}

}

resource “aws_subnet” “main1” {

vpc_id = “${aws_vpc.terra.id}”

cidr_block = “192.168.0.0/24”

availability_zone = “ap-south-1a”

map_public_ip_on_launch = “true”

tags = {

Name = “public”

}

}

resource “aws_subnet” “main2” {

vpc_id = “${aws_vpc.terra.id}”

cidr_block = “192.168.1.0/24”

availability_zone = “ap-south-1a”

tags = {

Name = “private”

}

}

So now we have one VPC and Under that two Subnet So for the public subnet, we are providing Internet gateway so that people can come from outside and see the front end service and for private Subnet, we are providing Nat gateway so that instance associate with it can go and download necessary things for all these we need routing table, internet gateway and nat gateway.

To create an Internet gateway, routing table write the following code

resource “aws_internet_gateway” “gw” {

vpc_id = “${aws_vpc.terra.id}”

tags = {

Name = “main”

}

}

resource “aws_route_table” “r” {

vpc_id = “${aws_vpc.terra.id}”

route {

cidr_block = “0.0.0.0/0”

gateway_id = “${aws_internet_gateway.gw.id}”

}

tags = {

Name = “newgateway”

}

}

So from the above code, we have successfully created an Internet gateway and routing table which has a route for internet gateway.

Now for creating Nat gateway you will first have to make elastic IP I have created from using web UI service for simplicity you can use code as well.

First go Aws home and select services

From this table select EC2

From the side menu select Elastic IPs

In the above image select allocate Ip

Again click on Allocate and finally you will see one IP like this is created

copy allocation ID and put in the above code

resource “aws_nat_gateway” “gw1”{

allocation_id = “Here you Allocation Id “

subnet_id = “${aws_subnet.main2.id}”

tags = {

Name = “NATgw”

}

}

resource “aws_route_table” “r2” {

vpc_id = “${aws_vpc.terra.id}”

route {

cidr_block = “0.0.0.0/0”

gateway_id = “${aws_nat_gateway.gw1.id}”

}

tags = {

Name = “natgateway”

}

}

Important these all services are not free although they are cheap but ya it cost something so be careful to destroy services after use and Nat gateway require Elastic Ip so after destroying the terra code remember to release Elastic IP.

Once this thing is done we need to attach route table to respective Subnets for that write the following code

resource “aws_route_table_association” “a” {

subnet_id = aws_subnet.main2.id

route_table_id = aws_route_table.r2.id

}

resource “aws_route_table_association” “a1” {

subnet_id = aws_subnet.main1.id

route_table_id = aws_route_table.r.id

}

Once it’s Done our subnet goes where to go and they manage things internally.

Now we have to create Security Groups for instances where we are launching three instances one instance for WordPress service, one for Bastion host, and one for the database.

resource “aws_security_group” “ServiceSG1” {

name = “For Worpress”

description = “Security for allowing ssh and 80”

vpc_id = “${aws_vpc.terra.id}”

ingress {

from_port = 22

to_port = 22

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”]

}

ingress {

from_port = 80

to_port = 80

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”]

}

egress {

from_port = 22

to_port = 22

protocol = “tcp”

cidr_blocks = [“0.0.0.0/0”]

}

}

The above security groups is for WordPress.

resource “aws_security_group” “ServiceSG2” {

name = “database service”

description = "Security for allowing ssh and MySQL port"

vpc_id = "${aws_vpc.terra.id}"

ingress {

from_port = 22

to_port = 22

protocol = "tcp"

security_groups = ["${aws_security_group.ServiceSG3.id}"]

}

ingress {

from_port = 3306

to_port = 3306

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"]

}

}

(remember to change ServiceSG to respective name in you case)

The above Security group is for Database

resource "aws_security_group" "ServiceSG3" {

name = "Bastion Host"

description = "Security for allowing ssh and 80"

vpc_id = "${aws_vpc.terra.id}"

ingress {

from_port = 22

to_port = 22

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"]

}

ingress {

from_port = 80

to_port = 80

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"]

}

}

The above security code is for Bastion Host.

Once this all is done we are ready to launch the instance here I use key pre-created by me if want to create the key from code and how to integrate Jenkins I would like to request to see my previous article here is the Link.

resource "aws_instance" "myin" {

ami ="ami-0447a12f28fddb066"

instance_type = "t2.micro"

availability_zone = "ap-south-1a"

key_name = "webserver"

vpc_security_group_ids = ["${aws_security_group.ServiceSG.id}"]

subnet_id= "${aws_subnet.main1.id}"

tags = {

Name = "Bastion Host"

}

}

resource "aws_instance" "myin2" {

ami ="ami-0447a12f28fddb066"

instance_type = "t2.micro"

availability_zone = "ap-south-1a"

key_name = "webserver"

vpc_security_group_ids = ["${aws_security_group.ServiceSG3.id}"]

subnet_id= "${aws_subnet.main1.id}"

tags = {

Name = "Wordpress"

}

}

resource "aws_instance" "myin1" {

ami ="ami-0447a12f28fddb066"

instance_type = "t2.micro"

availability_zone = "ap-south-1a"

key_name = "webserver"

vpc_security_group_ids = ["${aws_security_group.ServiceSG1.id}"]

subnet_id= "${aws_subnet.main2.id}"

tags = {

Name = "Database"

}

}

The above code will launch three instances one for WordPress which can access from the outside world and one Bation host to manage instance that has private IP and once instance for Database.

After wetting the whole code just type

terraform init

after that terraform plan

and when you see no error in the plan you are good to apply the things in aws and write the final command

terraform apply -auto-approve

you can also use terraform apply only -auto-approve is used so it don't ask yes or no.

After the above command, you see we have successfully created one vpc with two subnets private and public, internet gateway, nat gateway and routing table, and instances.

Guys for download full code you can go to this GitHub repo Link.

Below I have Shared Some Screenshot after running the full code.

Guys again important some service we used is not free they are cheap so remember to type terraform destroy -auto-approve at end and remember to release elastic IP you created manually.

Guys, I hope you like the article, and thanks for reading till here we have successfully created our system for deploying webserver.

--

--