Deploy a secured webserver for on AWS

Saptarsiroy
7 min readOct 13, 2020

What is VPC?

VPC stands for virtual private cloud. It consists of shared of shared computing resources that is allocated in a public environment and also providing some kind of isolation between the users or organization. If you didn’t understand this then in layman’s terms, VPC can be said to be a building inside which multiple labs can be created. Such labs are called subnets. Inside each subnet, multiple instances can be launched. Now each VPC can be configured to have a certain ip range inside which it will work. Ex. ‘10.0.0.0/16’ gives all ips from 10.0.0.0 to 10.0.255.255. The subnets can also be configured to divide this list into even smaller ones. For example, a VPC has ip in the range ‘10.0.0.0/16’ and a subnet inside the VPC can have the range ‘10.0.0.0/24’ or ‘10.0.1.0/24’.

In this demo, I will create a VPC in aws using terraform. Inside the VPC, I will create two labs or subnet. One can connect to the internet whereas the other could not. The use case for this would be launching a wordpress instance in the public subnet and a mysql instance in the private subnet.

To run the terraform code, you should have installed terraform and also configured aws profile to have power to create VPC and instance.

After doing all these, let’s get started.

First write the terraform code to provide the provider.

//Describing provider
provider "aws" {
region = "ap-south-1"
profile = "sappy"
}

After writing the provider, I am going to create three variables. The two variables would contain the contain the ami ids for wordpress and mysql. The third variable would contain the instance type. Here I am going for ‘t2.micro’ as it is in the free tier. Here is the code to create a variable in terraform.

//Creating variable for ami_wordpress
variable "ami_id_wordpress" {
type = string
default = "ami-000cbce3e1b899ebd"
}
//Creeating variable for ami_mysql
variable "ami_id_mysql" {
type = string
default = "ami-0019ac6129392a0f2"
}
//Creating Variable for instance type
variable "ami_type" {
type = string
default = "t2.micro"
}

After creating these variables, it is now time to interact with aws. The following code will create a private key that can be attached to the instance. This private key is necessary to establish ssh connectivity to the instance running, to execute some commands to update the app you are running. The code generates a ‘mykey.pem’ file where it will store the key.

//Creating Key
resource "tls_private_key" "tls_key" {
algorithm = "RSA"
}
//Generating Key-Value Pair
resource "aws_key_pair" "generated_key" {
key_name = "testkey111"
public_key = tls_private_key.tls_key.public_key_openssh
depends_on = [
tls_private_key.tls_key
]
}
//Saving Private Key PEM File
resource "local_file" "key-file" {
content = tls_private_key.tls_key.private_key_pem
filename = "mykey.pem"
depends_on = [
tls_private_key.tls_key
]
}

Now, it’s time to create VPC. My VPC will allow only certain ip range. Here it is ‘10.0.0.0/16’.

//Creating vpc
resource "aws_vpc" "sappyVPC" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
tags = {
name = "sappyVPC"
}
}

After creating the VPC, it is now time to create the labs or the subnets. Here, I am creating two subnets. The first one will have access to the public internet while the second one will be on the private network to prevent access. The wordpress instance will run on the public subnet while the MySql will run on the private subnet. This is to ensure that no one can connect to MySql and can access the database except WordPress.

//Public subnet for Wordpress
resource "aws_subnet" "publicSubnet" {
vpc_id = aws_vpc.sappyVPC.id
cidr_block = "10.0.0.0/24"
availability_zone = "ap-south-1a"
map_public_ip_on_launch = "true"
tags = {
name = "publicSubnet"
}
}
//Private subnet for mysql_user
resource "aws_subnet" "privateSubnet" {
vpc_id = aws_vpc.sappyVPC.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-south-1b"
tags = {
name = "privateSubnet"
}
}

But VPC, cannot on it’s own connect to the internet. We have to setup an internet gateway to allow connection. It provides the route table a target to allow internet traffic.

//Internet gateway
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.sappyVPC.id
tags = {
name = "publicGateway"
}
}

After creating the internet gateway we have to set up the route table. A route table contains all the necessary information for packet forwarding towards it’s destination. It provides the device with instructions for sending the packet to the next hop on its route across the network. Basically using the route table, we are creating a router virtually.

//creating route table
resource "aws_route_table" "r" {
vpc_id = aws_vpc.sappyVPC.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "publicTable"
}
}

Now it’s time to create firewall or called as security group(in aws). I will create two security groups. One would allow ssh from anywhere in the world and also http connection to access wordpress. The second security group is used to allow only ssh and enables port 3306, as MySql works on 3306 port.

//Creating Security Group for Wordpress
resource "aws_security_group" "wordpress-sg" {
name = "wordpress-sg"
description = "Wordpress Environment Security Group"
vpc_id = aws_vpc.sappyVPC.id
//Adding Rules to Security Group
ingress {
description = "SSH Rule"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTP Rule"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
//Creating Security Group for mysql
resource "aws_security_group" "mysql-sg" {
name = "mysql-sg"
description = "MySql Environment Security Group"
vpc_id = aws_vpc.sappyVPC.id
//Adding Rules to Security Group
ingress {
description = "SSH Rule"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Access mysql"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = [aws_vpc.sappyVPC.cidr_block]
}
}

Now, after creating all of these infrastructure it is time to launch our two instances. First I will create the MySql instance then the wordpress.

//Launching MySql
resource "aws_instance" "mysql" {
ami = var.ami_id_mysql
instance_type = var.ami_type
subnet_id = aws_subnet.privateSubnet.id
key_name = aws_key_pair.generated_key.key_name
vpc_security_group_ids = [aws_security_group.mysql-sg.id]
//Labelling the Instance
tags = {
Name = "mysql"
env = "Public"
}
depends_on = [
aws_security_group.mysql-sg,
aws_key_pair.generated_key
]
}
//Launching Wordpress
resource "aws_instance" "wordpress" {
ami = var.ami_id_wordpress
instance_type = var.ami_type
subnet_id = aws_subnet.publicSubnet.id
key_name = aws_key_pair.generated_key.key_name
vpc_security_group_ids = [aws_security_group.wordpress-sg.id]
//Labelling the Instance
tags = {
Name = "Wordpress"
env = "Public"
}
depends_on = [
aws_security_group.wordpress-sg,
aws_key_pair.generated_key
]
}

Finally, I am outputting the public ip of the wordpress instance so that i can connect to it.

output "IP_of_inst" {
value = aws_instance.wordpress.public_ip
}

Now that our code is ready, it is time to install terraform plugins. This command automatically downloads all the plugins required for to perform the operation.

terraform init
After init is successful

After downloading all the plugins, we have to validate our code to check if there are any errors or not.

terraform validate

This command does the job for you. If there are any errors, then it shows up in red color.

If there are no errors then it shows that the configuration is valid. Now it’s time to launch our setup.

terraform apply --auto-approve

The above command contacts aws cloud and launches everything for us. If everything is successfully launched then you will get the screen as shown below.

At the end, we are also getting out wordpress instance public ip for connectivity. If we use the ip to connect, then we can see the wordpress site is opening up.

WordPress site

Also if we check aws web console, then we can see that a new VPC has been created.

As we can see this VPC has a cidr block of ‘10.0.0.0/16’ . Also if we check the ec2 dashboard, there we can see two instance has been launched.

(In my case, you will be seeing two other instance which are terminated. Those are some experiments that I have been doing, so ignore that.)

This is the wordpress instance that has a public ip, so we can connect to it and access our site.

If we see the MySql instance, then we can see that it has no public ip hence, no one can have the access to it except wordpress.

Hence, we have successfully launched our setup on top of aws using terraform. Now if you want to delete it then use

terraform destroy --auto-approve

This command will destroy our setup completely. If this command is successful then you will get the screen as shown below.

Destroy setup

That’s it!!!

You have successfully deployed a Wordpress site on the public and also a MySql database privately as the backend. Hope you have enjoyed this article and please leave a clap if you do so.

I have completed this task after undergoing training from Mr. Vimal Daga sir. I want to thank him for teaching me and mentoring me in his course of “Hybrid Multi Cloud Computing” .

And lastly if you have liked my article then clap as any times as you want. It would be very helpful. Also follow my LinkedIn profile to see some more articles like this.

--

--