Create a VPC In AWS And Deploy Public WordPress Site With Private MYSQL Database Using Terraform

Things we do here:-

We have to create a web portal for our company with all the security as much as possible.

So, we use the WordPress software with a dedicated database server.

The database should not be accessible from the outside world for security purposes.

We only need the public WordPress to clients.

So here are the steps for proper understanding!


1) Write an Infrastructure as code using Terraform, which automatically creates a VPC.

2) In that VPC we have to create 2 subnets:

a) public subnet [ Accessible for Public World! ]

b) private subnet [ Restricted for Public World! ]

3) Create a public-facing internet gateway to connect our VPC/Network to the internet world and attach this gateway to our VPC.

4) Create a routing table for Internet gateway so that instance can connect to the outside world, update and associate it public subnet.with

5) Launch an ec2 instance that has WordPress setup already having to the security group allowing port 80 at our client can connect to our WordPress site.

Also, attach the key to the instance for further login into it.

6) 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.

Also, attach the key with the same.

Note: WordPress instance has to be part of the public subnet so that our client can connect our site.

MySQL instance has to be part of a private subnet so that the outside world can’t connect to it.


Virtual Private Cloud

Amazon Virtual Private Cloud (Amazon VPC) lets you provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define. You have complete control over your virtual networking environment, including a selection of your own IP address range, creation of subnets, and configuration of route tables and network gateways. You can use both IPv4 and IPv6 in your VPC for secure and easy access to resources and applications.

You can easily customize the network configuration of your Amazon VPC. For example, you can create a public-facing subnet for your web servers that have access to the internet. You can also place your backend systems, such as databases or application servers, in a private-facing subnet with no internet access. You can use multiple layers of security, including security groups and network access control lists, to help control access to Amazon EC2 instances in each subnet.


If a subnet’s traffic is routed to an internet gateway, the subnet is known as a public subnet. In this diagram, subnet 1 is a public subnet. If you want your instance in a public subnet to communicate with the internet over IPv4, it must have a public IPv4 address or an Elastic IP address (IPv4). For more information about public IPv4 addresses, see Public IPv4 addresses. If you want your instance in the public subnet to communicate with the internet over IPv6, it must have an IPv6 address.

If a subnet doesn’t have a route to the internet gateway, the subnet is known as a private subnet. In this diagram, subnet 2 is a private subnet.

If a subnet doesn’t have a route to the internet gateway but has its traffic routed to a virtual private gateway for a Site-to-Site VPN connection, the subnet is known as a VPN-only subnet. In this diagram, subnet 3 is a VPN-only subnet. Currently, we do not support IPv6 traffic over a Site-to-Site VPN connection.

In every subnet 1st, IP is reserved for — Network Name. 2nd IP is reserved for — Router.3rd IP is reserved for — DHCP Server.4th IP is reserved for — form some use case

Last IP is reserved for- Broadcasting

Internet Gateway

An internet gateway is a horizontally scaled, redundant, and highly available VPC component that allows communication between your VPC and the internet.

An internet gateway serves two purposes: to provide a target in your VPC route tables for internet-routable traffic and to perform network address translation (NAT) for instances that have been assigned public IPv4 addresses.

An internet gateway supports IPv4 and IPv6 traffic. It does not cause availability risks or bandwidth constraints on your network traffic.

Routing table

Routing table created inside VPC. The routing table consists of information on Internet Gateway. Apply this Routing Table to the subnet of DHCP Server in which instance want internet connectivity.


Create an account on AWS

Create an IAM user with Admin Access power and download the .csv file.

Install AWS CLI on your base os (In my case I am using windows).

Install terraform in your base OS. Install terraform using this link >>>

Now configure AWS then enter access key, Secret key and region.

Here I am expecting you already created a key pair.

this is the basic infrastructure blueprint of which we are going to creat

First, we have to give AWS credentials

provider "aws" {
region = "ap-south-1"
profile = "nischal"

Create VPC using terraform.

resource "aws_vpc" "main" {cidr_block       = ""instance_tenancy = "default"tags = {Name = "nischal_vpc"}}

Creating Public Subnet

resource "aws_subnet" "subnet1" {vpc_id     = aws_vpc.main.idavailability_zone = "ap-south-1a"cidr_block = ""map_public_ip_on_launch = truetags = {Name = "pub_1a"}}
resource "aws_subnet" "subnet2" {
vpc_id = aws_vpc.main.idavailability_zone = "ap-south-1b"cidr_block = ""tags = {Name = "pub_1b"}}

Creating Internet Gateway

resource "aws_internet_gateway" "gw" {vpc_id = "${}"tags = {Name = "int_gw"}}

Creating Routing Table

resource "aws_route_table" "rt" {vpc_id = "${}"route {cidr_block = ""gateway_id = "${}"}tags = {Name = "public"}}

Routing Table Association

resource "aws_route_table_association" "subnet_association" {subnet_id      = aws_subnet.subnet1.idroute_table_id =}

Create a WordPress Security Group

resource "aws_security_group" "allow_tls" {name        = "allow_tls"description = "Allow ssh,httpd,mysql"vpc_id      = "${}"ingress {description = "ssh port"from_port   = 22to_port     = 22protocol    = "tcp"cidr_blocks = [""]}ingress {description = "httpd port"from_port   = 80to_port     = 80protocol    = "tcp"cidr_blocks = [""]}ingress {description = " port"from_port   = 3306to_port     = 3306protocol    = "tcp"cidr_blocks = [""]}ingress {description = "ssh port"from_port   = 0to_port     = 0protocol    = -1cidr_blocks = [""]}egress {from_port   = 0to_port     = 0protocol    = "-1"cidr_blocks = [""]}tags = {Name = "sec_grp"}}

Create a Database Security Groups

resource "aws_security_group" "allow_public" {name        = "allow_public"description = "Allow ssh,httpd,mysql"vpc_id      = "${}"ingress {description = "TCP"from_port   = 3306to_port     = 3306protocol    = "tcp"security_groups =[]}egress{from_port   = 0to_port     = 0protocol    = "-1"cidr_blocks = [""]}tags = {Name = "sec_grp_for_privat"}}

Creating a WordPress Instance with Public Subnet

resource "aws_instance" "web" {ami          = "ami-000cdce3e1b899ebd"instance_type = "t2.micro"subnet_id  ="${}"associate_public_ip_address = truekey_name ="nischal"vpc_security_group_ids = []tags ={Name = "publicos"}}

Creating a Database Instance with Private Subnet

resource "aws_instance" "mysql" {ami          = "ami-08706cb5f68222d09"instance_type = "t2.micro"subnet_id  ="${}"key_name ="${var.ssh_key_name}"security_groups =[]tags ={Name = "mysql_privatos"}}


WordPress dashboard

We can destroy the complete infrastructure in one-click.

terraform destroy --auto-approve

You can find the Complete code in my GitHub

still, we can do something

adding NAT gateway so that the private subnet can get access to the internet in a secure level you can find that in this article

Connect me on my LinkedIn as well.