Configure Wordpress(Public Subnet) + Mysql(Private Subnet) + NAT Gateway on AWS using Terraform
6 min readOct 8, 2020
Prerequisite
- Have an AWS account.
- IAM Role created with permission(AdministratorAccess).
- Terraform download in OS.
- awscliv2 install and configured with IAM user.
Problem Statement:
- Write an Infrastructure as code using Terraform, which automatically creates a VPC.
- In that VPC we have to create 2 subnets:
- public subnet [ Accessible for Public World! ]
- private subnet [ Restricted for Public World! ]
- Create a public-facing internet gateway to connect our VPC/Network to the internet world and attach this gateway to our VPC.
- Create a routing table for Internet gateway so that instance can connect to the outside world, update and associate it with the public subnet.
- Create a NAT gateway to connect our VPC/Network to the internet world and attach this gateway to our VPC in the public network
- Update the routing table of the private subnet, so that to access the internet it uses the nat gateway created in the public subnet
- 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. Also, attach the key to the instance for further login into it.
- 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.
Step-1)Create VPC
- use resource aws_vpc for creating VPC.
- Code:
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"tags = {
Name = "VPC_MY"
}
}
- Here I am using 10.0.0.0/16 in cidr_block.
Step-2)Create Public Subnet
- Use resource aws_subnet for creating subnet.
- Code:
resource "aws_subnet" "wp_public" {
depends_on=[
aws_vpc.main
]
vpc_id = aws_vpc.main.id
cidr_block = "10.0.0.0/24"
map_public_ip_on_launch = true
availability_zone = "ap-south-1a"tags = {
Name = "wordpress_pub"
}
}
- Here I am using 10.0.0.0/24 in cidr_block.
Step-3)Create Private Subnet
- Use resource aws_subnet for creating subnet.
- Code:
resource "aws_subnet" "mq_private" {
depends_on=[
aws_vpc.main
]
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "ap-south-1a"tags = {
Name = "mysql_pub"
}
}
- Here I am using 10.0.1.0/24 in cidr_block.
Step-4)Create Internet Gateway
- Use resource aws_internet_gateway for creating an internet gateway.
- Code:
resource "aws_internet_gateway" "IG" {
depends_on=[
aws_vpc.main
]
vpc_id = aws_vpc.main.idtags = {
Name = "IG_MY"
}
}
Step-5)Create EIP:
- use resource aws_eip for creating of EIP.
- Code:
resource "aws_eip" "EIP" {
depends_on=[aws_internet_gateway.IG]
vpc = true
}
Step-6)Creating NAT Gateway.
- use resource aws_nat_gateway for creating nat.
- Code:
resource "aws_nat_gateway" "NAT" {
depends_on=[aws_internet_gateway.IG,aws_eip.EIP,]
allocation_id = aws_eip.EIP.id
subnet_id = aws_subnet.wp_public.idtags = {
Name = "gw_nat"
}
}
Step-7) Create Route Table and associate it.
- Code:
resource "aws_route_table" "myroute" {
depends_on=[aws_internet_gateway.IG]
vpc_id = aws_vpc.main.idroute {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.IG.id
}tags = {
Name = "route_my"
}
}resource "aws_route_table_association" "a" {
depends_on=[aws_route_table.myroute]
subnet_id = aws_subnet.wp_public.id
route_table_id = aws_route_table.myroute.id
}
- Here first we need to create a Route table using aws_route_table resource and add a route in cidr_block(0.0.0.0/0).
- Use Internet Gateway ID which we created above.
- for the association route table, use aws_route_table_association resource.
- Here we need to add our public subnet in the route table because second for MySQL which is private.
Step-8) Create a Security Group for WordPress EC2 Instance.
- Code:
resource "aws_security_group" "sg_wordpress" {
depends_on=[
aws_route_table_association.a
]
name = "mywordpresssg"
description = "for wordpress port"
vpc_id = aws_vpc.main.idingress {
description = "HTTP from VPC"
from_port = 80
to_port = 80
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"]
}
ingress {
description = "ssh from VPC"
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 = "wordpress_sec"
}
}
- Here we have to use 80 port for a WordPress Port, and 22 for ssh if we need to connect it.
Step-9) Create a Security Group for Mysql EC2 Instance.
- Code:
resource "aws_security_group" "sg_mysql" {
depends_on=[
aws_security_group.sg_wordpress
]
name = "formysql"
description = "formysqlport"
vpc_id = aws_vpc.main.idingress {
description = "mysqport"
from_port = 3306
to_port = 3306
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"]
}
ingress {
description = "ssh from VPC"
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 = "mysql_sec"
}
}
- Here we have to use the 3306 port for MySQL.
- Here I am using 22 port for ssh and to log in this MySQL we have to make one bastion host I made WordPress Ec2 as a bastion host.
Step-10) Creating Key.
- Code
resource "tls_private_key" "mykey"{
depends_on=[aws_security_group.sg_mysql]
algorithm = "RSA"
}resource "tls_private_key" "key_ssh" {
depends_on=[tls_private_key.mykey]algorithm = "RSA"
rsa_bits = 4096
}
resource "aws_key_pair" "key5" {
depends_on=[tls_private_key.key_ssh]
key_name = "key5"
public_key = tls_private_key.key_ssh.public_key_openssh
}
output "key_ssh" {
value = tls_private_key.key_ssh.private_key_pem
}
resource "local_file" "save_key" {
depends_on=[aws_key_pair.key5]
content = tls_private_key.key_ssh.private_key_pem
filename = "key5.pem"
}
- Here I am using resources tls_private_key for creating key and local_file for saving our key.
Step-11)Launch WordPress
- Code:
resource "aws_instance" "wp_public" {
depends_on=[
tls_private_key.mykey,
tls_private_key.key_ssh,
aws_key_pair.key5,
local_file.save_key,
]
ami = "ami-0006cd66ea9360e37"
instance_type = "t2.micro"
key_name = "key5"
availability_zone = "ap-south-1a"
subnet_id = aws_subnet.wp_public.id
vpc_security_group_ids = [aws_security_group.sg_wordpress.id]tags = {
Name = "wordpress_public"
}
}
- Here we have to use the public subnet which we created above.
- Use Security Group which we created above
- Provide it key because in the future if we want to login.
Note:
- Here I am using my own AMI id which I have already configured WordPress and Mysql.
Step-12)Launch Mysql
- Code:
resource "aws_instance" "mys_priv" {
depends_on=[
aws_instance.wp_public
]
ami = "ami-04b1ce4bbc6ea87d6"
instance_type = "t2.micro"
availability_zone = "ap-south-1a"
subnet_id = aws_subnet.mq_private.id
vpc_security_group_ids = [aws_security_group.sg_mysql.id]tags = {
Name = "mysql_private"
}
}
Step-13)Setup Host Mysql in wp-config.php file
- Code:
resource "null_resource" "null1"{
depends_on = [
aws_instance.wp_public,
aws_instance.mys_priv
]
connection {
type = "ssh"
user = "ubuntu"
private_key = tls_private_key.key_ssh.private_key_pem
host = aws_instance.wp_public.public_ip
}provisioner "remote-exec" {
inline = [
"cd /var/www/wordpress/",
"sudo sed -i 's/myhost/${aws_instance.mys_priv.private_ip}/g' wp-config.php",
]
}
}
Step-14)Giving permission for Key.
- We need to transfer the key into WordPress instance for the login of MySQL instance
- For this, we need to give permission to the key.
resource "null_resource" "null2" {
depends_on = [
null_resource.null1,
]
provisioner "local-exec" {
command = "chmod 400 key.pem"
}
}
Step-15)Transfer the key.
- Use scp to transfer the key.
- Code:
resource "null_resource" "null3"{
depends_on=[null_resource.null2]
provisioner "local-exec" {
command="scp -i key5.pem key5.pem ubuntu@{aws_instance.wp_public.public_ip}:/home/ubuntu/key5.pem"
}
}
Command to run code:
terraform init
- init for Initialization terraform plugins.
terraform apply --auto-approve
- apply to run the terraform code.