WordPress Web-server with Secure Mysql Database in AWS

Abhishek Mishra
5 min readAug 18, 2020

In this post, we are going to deploy a complete infrastructure of WordPress with MySQL database in which only WordPress can access to MySQL instance.

What is WordPress?

WordPress is a free and open-source content management system written in PHP and paired with a MySQL or MariaDB database.

What is Terraform?

Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions.

It an open-source infrastructure as a code software tool created by HashiCorp. It enables users to define and provision a data center infrastructure using a high-level configuration language known as Hashicorp Configuration Language.

Task Overview —

  1. Write an Infrastructure as code using Terraform, which automatically creates a VPC.
  2. In that VPC we have to create 2 subnets:
  3. public subnet [ Accessible for Public World! ]
  4. private subnet [ Restricted for Public World! ]
  5. Create a public-facing internet gateway to connect our VPC/Network to the internet world and attach this gateway to our VPC.
  6. Create a routing table for Internet gateway so that instance can connect to the outside world, update and associate it with the public subnet.
  7. Launch an ec2 instance that has WordPress setup already having the security group allowing port 80 so that our client can connect to our WordPress site.
  8. Launch an ec2 instance that has MYSQL setup already with security group allowing port 3306 in a private subnet so that our WordPress VM can connect with the same.

Procedure —

Step 1

Create a file with an extension .tf

Step 2

Write the code in the same.

Providing credentials to AWS —

provider “aws” {region = “ap-south-1”profile = “default”}

Creating a VPC —

resource "aws_vpc" "task_vpc" {cidr_block       = "192.168.0.0/16"instance_tenancy = "default"tags = {Name = "Task-3"}}

Creating a public and private subnet —

resource "aws_subnet" "public_subnet" {depends_on = [ aws_vpc.task_vpc]vpc_id     = aws_vpc.task_vpc.idcidr_block = "192.168.3.0/24"availability_zone = "ap-south-1a"tags = {Name = "public_subnet"} }resource "aws_subnet" "private_subnet" {depends_on = [ aws_vpc.task_vpc]vpc_id     = aws_vpc.task_vpc.idcidr_block = "192.168.2.0/24"availability_zone = "ap-south-1b"tags = {Name = "private_subnet"} }

Create an gateway —

resource "aws_internet_gateway" "task_ig" {depends_on = [ aws_vpc.task_vpc ]vpc_id = aws_vpc.task_vpc.idtags = {Name = "task_ig"}}

Create a route table and route table association —

resource "aws_route_table" "router" {depends_on = [ aws_internet_gateway.task_ig ]vpc_id = aws_vpc.task_vpc.idroute {cidr_block = "0.0.0.0/0"gateway_id = aws_internet_gateway.task_ig.id}tags = {Name = "router_task"} }resource "aws_route_table_association" "router-association" {depends_on = [ aws_route_table.router ]subnet_id      = aws_subnet.public_subnet.idroute_table_id = aws_route_table.router.id}

Create AWS Eib , routing table and nat gateway —

resource "aws_eip" "task_ip" {vpc      = truedepends_on = [aws_internet_gateway.task_ig]}resource "aws_nat_gateway" "task_nat" {allocation_id = aws_eip.task_ip.idsubnet_id     = aws_subnet.public_subnet.idtags = {Name = "task NAT"} }resource "aws_route_table" "nat_route" {depends_on = [aws_nat_gateway.task_nat]vpc_id = aws_vpc.task_vpc.idroute {cidr_block = "0.0.0.0/0"nat_gateway_id = aws_nat_gateway.task_nat.id}tags = {Name = "NAT_RouteTable"}}
resource "aws_route_table_association" "NAT_assocation" {depends_on = [aws_subnet.private_subnet, aws_route_table.nat_route]subnet_id = aws_subnet.private_subnet.idroute_table_id = aws_route_table.nat_route.id}

Create an Security Group for MYSQL instance —

resource "aws_security_group" "MySQL_SG" {depends_on = [aws_security_group.WP_SG]name        = "SG_MySQL"description = "Allow TLS inbound traffic"vpc_id      = aws_vpc.task_vpc.idingress{description = "SSH"from_port = 22to_port = 22security_groups =[ aws_security_group.WP_SG.id]protocol = "tcp"cidr_blocks = ["0.0.0.0/0"]}ingress {description = "MySQL"from_port   = 3306to_port     = 3306protocol    = "tcp"cidr_blocks = ["0.0.0.0/0"]}ingress {description = "MySQL redirection"from_port   = 8080to_port     = 8080protocol    = "tcp"cidr_blocks = ["0.0.0.0/0"]}egress {from_port   = 0to_port     = 0protocol    = "-1"cidr_blocks = ["0.0.0.0/0"]}tags = {Name = "MySQL_SG"}

Launching an ec2 instance using custom AMI —

Note — The ami used was creating by me using amazon linux and installing docker in the same.

resource "aws_instance" "MySQL" {depends_on = [aws_security_group.MySQL_SG, tls_private_key.task_key]ami           = "ami-04ca6b22ca88bdbea"instance_type = "t2.micro"key_name = "task_key"vpc_security_group_ids = [ aws_security_group.MySQL_SG.id ]subnet_id = aws_subnet.private_subnet.iduser_data = <<-EOF#!/bin/bashsudo docker run -dit -p 8080:3306 --name mysql -e MYSQL_ROOT_PASSWORD=master -e MYSQL_DATABASE=Task-3-db -e MYSQL_USER=anmol -e MYSQL_PASSWORD=redhat mysql:5.6EOFtags = {Name = "MySQL-OS"}}

Generating private key and storing it to local storage —

resource "tls_private_key" "task_key" {algorithm   = "RSA"}# Saving to local systemresource "local_file" "save_key" {depends_on = [ tls_private_key.task_key]content   = tls_private_key.task_key.private_key_pemfilename  = "task_key.pem"}# Sending public key to awsresource "aws_key_pair" "public_key" {depends_on = [local_file.save_key]key_name = "task_key"public_key = tls_private_key.task_key.public_key_openssh}

Creating a Security group for Wordpress Instance —

resource "aws_security_group" "WP_SG" {
name = "WordPress_SG"
description = "Allow TLS inbound traffic"
vpc_id = aws_vpc.task_vpc.id

ingress{
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Http port"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Http redirection"
from_port = 8000
to_port = 8000
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 = "WordPress_SG"
}
}

Launching an ec2 instance for wordpress using custom ami and running wordpress on Docker —

Note — The ami used was creating by me using amazon linux and installing docker in the same.

resource "aws_instance" "WordPress" {depends_on = [tls_private_key.task_key, aws_security_group.WP_SG]ami           = "ami-04ca6b22ca88bdbea"instance_type = "t2.micro"associate_public_ip_address = truevpc_security_group_ids = [ aws_security_group.WP_SG.id ]subnet_id = aws_subnet.public_subnet.idkey_name = "task_key"user_data = <<-EOF#!/bin/bashsudo docker run -dit -p 8000:80 --name wp wordpress:4.8-apacheEOFtags = {Name = "WordPress-OS"}}

To run the above code —

terraform apply

Note — make sure to delete the infrastructure as soon as your task is complete, to avoid unnecessary billing.

terraform destory

Output —

Open the public Ip of Wordpress instance and enter the credentials of the MYSQL Database created in other ec2 instance.

--

--