Launching of wordpress and mysql with bastion os for updating mysql

Sahil Raj
7 min readJul 31, 2020

--

In this article we launch a Wordpress site with mysql as database.We launch the wordpress instance in public subnet so that clients can connect to it.We launch the mysql server in private subnet as it contains critical data so we do not give any internet connection to this subnet and thus the instance cannot connect to outside world and nobody can initiate the connection to our mysql instance.This setup arises a problem for us that since our mysql server cannot connect to the outside world how will it get updated.We use a bastion host os for that ,we create an bastion instance in the public subnet and due to internal connectivity of the subnets, we first connect to the bastion host and then we connect to the mysql instance through bastion host and connect to internet with the help of nat gateway.

problem statement:

  1. Write a code to create a vpc in aws and create public as well as private subnet.
  2. Create a public facing internet gateway and attach it to our vpc.
  3. Create a routing table for internet gateway so that instance can connect to outside world,update and associate it with public subnet.
  4. Create a NAT gateway to connect our vpc network to the internet world and attach this gateway to our vpc in the public subnet.
  5. Update the routing table of private subnet ,so that it can access the internet by using the nat gateway.
  6. Launch an ec2 instance which has wordpress setup having security group allowing port 80 for our clients to connect to our wordpress site.Also attach the key to instance and do the same thing with msql allowing port 3306.
  7. Wordpress instance has to be a part of public subnet so that our clients can connect to our site. Mysql instance has to be a part of private subnet so that anybody from outside world cannot initiate a connection to our instance.

Step 1:Create aprofile in aws by aws cli command .We use this profile to login to aws.

provider "aws" {
region = "ap-south-1"
profile = "sahil123"
}

Now we use a command to initialize a working directory which contains terraform config files.

terraform init

Step 2:

We create our own vpc with a specific ip range.Any instance created in any subnet of this vpc will get its private ip from this allocated range.We enable hostname option to give hostname to any instance launched in this vpc.

resource "aws_vpc" "sahil-vpc" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
enable_dns_hostnames = true
tags = {
Name = "sahil-vpc"
}
}

After this we create a public subnet and a private subnet and provide ip range to them from the ip range provided to the vpc.

resource "aws_subnet" "public-subnet" {
vpc_id = "${aws_vpc.sahil-vpc.id}"
cidr_block = "10.0.0.0/24"
availability_zone = "ap-south-1a"
map_public_ip_on_launch = true
tags = {
Name = "sahil-public-subnet"
}
}
resource "aws_subnet" "private-subnet" {
vpc_id = "${aws_vpc.sahil-vpc.id}"
cidr_block = "10.0.1.0/24"
availability_zone = "ap-south-1a"
tags = {
Name = "sahil-private-subnet"
}
}

Step 3:

We create an internet gateway and attach it to the our vpc as a means to connect to outside world and anybody from outside world can initiate a connection.After that we create a routing table and add a rule in it that if any instance wants to connect to internet it can use this internet gateway.We associate this routing table with the public subnet so that the the Dhcp server in the public subnet gets updated with this rule and tell the location of the internet gateway to any instance for it to connect to public world.

resource "aws_internet_gateway" "gw" {
vpc_id = "${aws_vpc.sahil-vpc.id}"
tags = {
Name = "sahil-gateway"
}
}
resource "aws_route_table" "routing-table" {
vpc_id = "${aws_vpc.sahil-vpc.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.gw.id}"
}
}
resource "aws_route_table_association" "subnet-association" {
subnet_id = aws_subnet.public-subnet.id
route_table_id = aws_route_table.routing-table.id
}

To create the internet gateway we have to provide it with the vpc id as we attach it to a specific vpc and other required id’s as well.

Step 4:

We create a NAT gateway for the mysql instance so that it can connect to internet and we can update it.We use Nat gateway for this as nobody from the outside world can initiate connection to the mysql instance.We create the nat gateway in public subnet as the public subnet has the internet connection and internally it uses the internet gateway for connecting to the internet.Since to create a nat gateway an instance is launched in aws not visible to us ,it needs a public ip for connection. We create a routing table and add a rule to it to use the nat gateway for connecting to internet and associate it with the private subnet.

resource "aws_eip" "sahil-eip" {
vpc = true
}
resource "aws_nat_gateway" "nat-gateway" {
allocation_id = "${aws_eip.sahil-eip.id}"
subnet_id = "${aws_subnet.public-subnet.id}"
tags = {
Name = "sahil-NAT"
}
}
resource "aws_route_table" "nat-routing-table" {
vpc_id = "${aws_vpc.sahil-vpc.id}"
route {
cidr_block = "0.0.0.0/0" #any ip can connect to internet
nat_gateway_id = "${aws_nat_gateway.nat-gateway.id}"
}
}
resource "aws_route_table_association" "nat-association" {
subnet_id = aws_subnet.private-subnet.id
route_table_id = aws_route_table.nat-routing-table.id
}

Step 5:

We create security groups for the bastion os through which we will connect to mysql instance and update it.We would allow port 22 as we will do ssh from outside world and thus keep it in public subnet. Create a security group for wordpress instance and allow port 80 for users to connect. Create the security group for the mysql instance allow the instances which has security group of wordpress and bastion host and allow port 3306 so that wordpress instance can connect to it.

resource "aws_security_group" "bastion-sg" {
name = "bastion-sg"
description = "Allow ssh from public world outside"
vpc_id = "${aws_vpc.sahil-vpc.id}"
ingress {
description = "allow port 22"
from_port = 22
to_port = 22
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 = "bastion-sg"
}
}
resource "aws_security_group" "wordpress-sg" {
name = "wordpress-sg"
description = "Allow ssh and httpd"
vpc_id = "${aws_vpc.sahil-vpc.id}"
ingress {
description = "allow httpd from public world"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "allow ssh from public world"
from_port = 22
to_port = 22
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 = "allow_port_80"
}
}
resource "aws_security_group" "mysql" {
name = "mysql-sg"
description = "Allow port 3306 and sg of wordpress"
vpc_id = "${aws_vpc.sahil-vpc.id}"
ingress {
description = "allow 3306"
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = ["${aws_security_group.wordpress-sg.id}"]
}
ingress {
description = "allow ssh from public world"
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.bastion-sg.id}"]

}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "mysql-sg"
}
}

step 6:

Now we create a bastion os in public subnet and copy the key in it to ssh to the mysql os.We create a mysql and a wordpress instance and attach the key in it it.We launch the instances in public and private instance respectively.

resource "aws_instance" "bastion-os" {
ami = "ami-0ebc1ac48dfd14136"
instance_type = "t2.micro"
key_name = "mykey11"
vpc_security_group_ids = ["${aws_security_group.bastion-sg.id}"]
subnet_id ="${aws_subnet.private-subnet.id}"
tags = {
Name = "sahil-bastion"
}
}
resource "aws_instance" "mysql-server" {
ami = "ami-0019ac6129392a0f2"
instance_type = "t2.micro"
key_name = "mykey11"
vpc_security_group_ids = ["${aws_security_group.mysql.id}"]
subnet_id ="${aws_subnet.private-subnet.id}"
tags = {
Name = "sahil-mysql"
}

}
resource "aws_instance" "wordpress-server" {
ami = "ami-000cbce3e1b899ebd"
instance_type = "t2.micro"
key_name = "mykey11"
vpc_security_group_ids = ["${aws_security_group.wordpress-sg.id}"]
subnet_id = "${aws_subnet.public-subnet.id}"
tags = {
Name = "sahil-wordpress"
}
}

Now we use :

terraform apply -auto-approve

Security group created:

Eip alloted:

NAT gateway created and used in routing table:

VPC created:

Public and private subnets created:

Internet gateway created and attached to vpc and routing table created with the rule of using internet gateway and the table is associated with the public subnet.

The three instances created:

Now we use this command to destroy the whole setup:

terraform destroy -auto-approve

--

--

Sahil Raj
Sahil Raj

No responses yet