top of page

DEPLOYING WORDPRESS AND MYSQL ON CUSTOM VPC WITH NAT USING TERRAFORM



If you check my previous story, you can see that it had a similar to this one. The only difference is that the instances in the private subnet(MySQL) do not have any internet connectivity. This story will show you how to setup the whole thing with internet connectivity on both private and public subnets.


Internet connectivity on private subnets can be achieved using NAT gateways.


NAT Gateway

A NAT gateway gives cloud resources without public IP addresses access to the internet without exposing those resources to incoming internet connections.

Pre-requisites:-

  1. AWS account

  2. AWS CLI installed and configured

  3. Terraform installed and added to path

  4. VSCode with HashiCorp Terraform and Terraform Autocomplete plugins installed

Process:-

1. First we need to create the provider. Our provider is AWS therefore, we select AWS with other relevant information like the credentials.

provider "aws" 
{
region                  = "ap-south-1"
shared_credentials_file = "C:/Users/KIIT/.aws/credentials"
profile                 = "chirag"
}

2. Next we shall create the key pairs which shall be used to remotely login to the instances.

resource "tls_private_key" "keypair" {
algorithm   = "RSA"
}
resource "local_file" "privatekey" {
content     = tls_private_key.keypair.private_key_pemfilename = "key1.pem"
}
resource "aws_key_pair" "deployer" {
key_name   = "key1.pem"
public_key = tls_private_key.keypair.public_key_openssh
}

3. We shall now start with the VPC creation. The VPC will have many parts namely subnets, ip-routing tables for each subnet, internet gateway for the public subnet, nat gateway for the private subnet, etc.

resource "aws_vpc" "main" {
cidr_block       = "192.168.0.0/16"
instance_tenancy = "default"tags = {
Name = "myvpc"
}
}

4. A subnet is like a sub-network within an even bigger network(VPC). In this case we shall create 2 subnets under the VPC we just created. One will be a public subnet while the other one is going to be a private one. We shall create the Wordpress instance in the public instance as it requires internet connectivity. MySQL instance will be created in private subnet as we don’t want it to be exposed to the outside world.


5. We shall create the following Routes and Routing tables(A routing table is a data table stored in a router or a network host that lists the routes to particular network destinations, and in some cases, metrics associated with those routes.).

resource "aws_route_table" "routetable1" {
vpc_id    = aws_vpc.main.id
}
resource "aws_route" "route1" {
route_table_id         = aws_route_table.routetable1.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.intgw.id
}
resource "aws_route_table_association" "routetableassoc1" {
subnet_id      = aws_subnet.subnet1.id
route_table_id = aws_route_table.routetable1.id
}
resource "aws_route_table" "routetable2" {
vpc_id    = aws_vpc.main.id
}
resource "aws_route" "route2" {
route_table_id         = aws_route_table.routetable2.id
destination_cidr_block = "0.0.0.0/0"
instance_id= aws_instance.wordpress.id
}
resource "aws_route_table_association" "routetableassoc2" {
subnet_id      = aws_subnet.subnet2.id
route_table_id = aws_route_table.routetable2.id
}
resource "aws_subnet" "subnet1" {
vpc_id            = aws_vpc.main.id
availability_zone = "ap-south-1a"
cidr_block        = "192.168.1.0/24"
map_public_ip_on_launch="true"
tags              = map("Name","Subnet1")
}
resource "aws_subnet" "subnet2" {
vpc_id            = aws_vpc.main.id
availability_zone = "ap-south-1a"
cidr_block        = "192.168.2.0/24"
map_public_ip_on_launch="false"tags              = map("Name","Subnet2")
}

6. 1 internet gateway and 1 NAT gateway will be created to give internet connectivity to the public and private subnet respectively.

resource "aws_internet_gateway" "intgw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "main"
}
}
resource "aws_eip" "nat" {
vpc = true
depends_on                = [aws_internet_gateway.intgw]
}
resource "aws_nat_gateway" "natgw" {
allocation_id = aws_eip.nat.id
subnet_id     = aws_subnet.subnet2.id
depends_on = [aws_internet_gateway.intgw]
tags = {
Name = "gw NAT"}
}

7. Security Groups are very important as they filter out any undesirable traffic to the instances. For both the instances we shall create 1 security group each that will prevent any undesirable connection to and from the instances.

resource "aws_security_group" "secure1" {
name          = "secure1"
vpc_id        = aws_vpc.main.id
description   = "Allow TLS inbound traffic"
ingress {
description = "SSH"
from_port   = 22
to_port     = 22
protocol    = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTP"
from_port   = 80
to_port     = 80
protocol    = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "WORDPRESS"
from_port   = 443
to_port     = 443
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"]
}
tags = {
Name = "subnet1sg"
}
}
resource "aws_security_group" "secure2" {
name          = "secure2"
vpc_id        = aws_vpc.main.id
description   = "Allow TLS inbound traffic"
ingress {
description = "SSH"
from_port   = 22
to_port     = 22
protocol    = "tcp"
cidr_blocks = [aws_subnet.subnet1.cidr_block]
}
ingress {
description = "MYSQL"
from_port   = 3306
to_port     = 3306
protocol    = "tcp"
cidr_blocks = [aws_subnet.subnet1.cidr_block
]
}
egress {
from_port   = 0
to_port     = 0
protocol    = "-1"
cidr_blocks = ["0.0.0.0/0"]}
tags = {
Name = "subnet2sg"
}
}

8. Now that all the components of the VPC are created we shall create the instances.

resource "aws_instance"  "wordpress" {
ami           = "ami-7e257211"
instance_type = "t2.micro"
subnet_id     = aws_subnet.subnet1.id
key_name  = aws_key_pair.deployer.key_name
security_groups =  [aws_security_group.secure1.id]
vpc_security_group_ids = [aws_security_group.secure1.id]
associate_public_ip_address = true
depends_on = [aws_internet_gateway.intgw]
tags = {
Name = "Wordpress"
}
}
resource "aws_instance"  "mysql" {
ami           = "ami-0979674e4a8c6ea0c"
instance_type = "t2.micro"
subnet_id     = aws_subnet.subnet2.id
key_name      = aws_key_pair.deployer.key_name
security_groups =  [aws_security_group.secure2.id]
vpc_security_group_ids = [aws_security_group.secure2.id]
associate_public_ip_address = false
tags = {
Name = "Mysql"
}
}

9. We shall create a separate file output.tf that will display some of the important info like instance IDs, IPs etc. This file will also launch the website on chrome.

output.tf

resource "null_resource" "publicip"  {
provisioner "local-exec" {
command = "echo  ${aws_instance.wordpress.public_ip} > publicip.txt"
}
}
resource "null_resource" "privateip"  {
provisioner "local-exec" {
command = "echo  ${aws_instance.mysql.private_ip} > privateip.txt"
}
}
resource "null_resource" "nulllocal1"  {
provisioner "local-exec" {
command = "start chrome  ${aws_instance.wordpress.public_ip}"
}
depends_on = [
aws_instance.wordpress
]
}
output "wordpressid"{
value=aws_instance.wordpress.id
}
output "mysqlid"{
value=aws_instance.mysql.id
}
output "eipid"{
value=aws_eip.nat.id
}
output "eippublicip"{
value=  aws_eip.nat.public_ip
}

10. Use the following code in terminal to launch the setup.

terraform init
terraform apply -auto-approve

Terraform init will install the required plugins and it is a compulsory command when executing terraform for 1st time in the folder.





source: medium


The Tech Platform


0 comments

Comments


bottom of page