Deploy a WordPress Website on AWS

Eugene Miguel
52 min readMay 4, 2023

--

I will walk you through deploying a WordPress website on AWS using the management console

Requirements

  1. AWS Certified Cloud Practitioner CLF-C01
  2. AWS Certified Solutions Architect Associate SAA-C03
  3. Don’t just complete the project. Its important that you understand why we are using these technologies and how they work together

Introduction

I am glad to see you here again for our next real world project! We will learn how to deploy this dynamic website on AWS. We will also learn how to use my reference architecture to host this website using various AWS services and how they work together:

  • VPC with public and private subnets
  • Security groups
  • EC2 instances
  • NAT gateways
  • RDS
  • Application load balancer
  • Route 53
  • Auto scaling group
  • Certificate manager
  • EFS and more

Objective

  1. Build a three-tier AWS network VPC from scratch
  2. Create NAT gateways
  3. Create the security groups
  4. Create the RDS instance
  5. Create the elastic file system
  6. Create a key pair
  7. Download putty
  8. Launch the setup server
  9. SSH into an EC2 instance in the public subnet
  10. Create an application load balancer
  11. Register a new domain name in Route 53
  12. Create a record set in route 53
  13. Register for an SSL certificate in AWS certificate manager
  14. Launch bastion host
  15. SSH into an instance in the private subnet
  16. Create an HTTPS listener for the application load balancer
  17. Create an auto scaling group
  18. Install WordPress theme and template
  19. Clean up
VPC Reference Architecture

This is an excellent project to present during an interview

We will start by creating a custom 3-tier VPC using the reference architecture above. In a 3-tier reference architecture, our infrastructure is divided into 3 tiers.

Tier 1 — we have the public subnet which will hold the resources such as NAT gateway, load balancer, and bastion host

Tier 2 — this is our private subnet which will hold our web servers (EC2 instances)

Tier 3 — another private subnet which will hold our database

We will duplicate these subnets across multiple availability zones for high availability and fault tolerance.

Lastly, we will create an internet gateway and route table to allow the resources in our VPC to have access to the internet.

Let’s begin!

VPC Reference Architecture

  1. VPC with public and private subnets in 2 availability zones
  2. An internet gateway is used to allow communication between instances in VPC and the internet
  3. We are using 2 availability zones for high availability and fault tolerance
  4. Resources such as NAT gateway, bastion host, and application load balancer use public subnets.
  5. We will put the web servers and database servers in the private subnets to protect them
  6. The public route table is associated with the public subnets and routes traffic to the internet through the internet gateway
  7. The main route table is associated with the private subnets

Part 1: Build a Three-Tier AWS Network VPC from Scratch

VPC

In the management console, select the region where we want to create our VPC. According to our reference architecture we need to create this VPC in the N. Virginia region.

Either select VPC from the console or type VPC in the search bar above.

In your VPC dashboard select VPCs or the Create VPC orange box

Let’s give our VPC a name. Let’s select VPC only and call it Dev VPC.

Based on our reference architecture we will enter 10.0.0.0/16 in the IPv4 CIDR block.

We will leave the IPv6 CIDR block and Tenancy to default. Let’s click Create VPC at the bottom right.

It will give us a successfully created message

We can also see all the VPC that we created by clicking the drop down arrow on Select a VPC box — let’s choose the one we just created

Let’s enable the DNS host name in our VPC by selecting Actions and Edit VPC settings

Under Edit VPC settings make sure that Enable DNS hostnames is checked then click Save

We have successfully enabled the DNS hostnames in our VPC

Internet Gateway

The next thing we are going to do is to create an Internet gateway for our VPC. You can find and select Internet gateway at the left side menu of Your VPC

Let’s select Create Internet gateway, give it a name — Dev Internet Gateway and click Create internet gateway

Now, we need to attach the internet gateway to the VPC we created earlier. This will allow the VPC to communicate with the internet.

Just simply click Attach to a VPC in the green banner above

Select the Dev VPC that we created and click Attach internet gateway. This is the only VPC that will show in your account this doesn’t have any internet gateway attached to it. We can only attach one internet gateway to one VPC

We successfully attached the internet gateway to our VPC. The Details show the State and the VPC ID

Public Subnets

Let’s create our public subnets in the first and second availability zones. Ensure that its still filtered to our Dev VPC then click Subnets at the left side.

Once you are in the subnet page, click Create subnet

Let’s select the VPC where we want to create our subnet in — let’s choose Dev VPC

Let’s give our subnet a name. Based on our reference architecture, we will call it Public Subnet AZ1 and put this in the us-east-1a Availability Zone

The CIDR block should be 10.0.0.0/24 and click Create subnet

We have successfully created our first public subnet in the us-east-1a Availability Zone.

Let’s create our second subnet in the us-east-1b Availability Zone and click the Create subnet button at the top right.

Select the same VPC

We are going to call it Public Subnet AZ2 and place it in us-east-1b Availability Zone — based on our reference architecture

Select and enter 10.0.1.0/24 in IPv4 CIDR block. Afterwards we can Create subnet

Good work! We have successfully created our 2nd public subnet in the us-east-1b Availability Zone. If you select Clear filters it will show you the 2 subnets that we created this region — remember to filter it to your Dev VPC to populate these

Remember to check the following:

Public Subnet AZ1 is in us-east-1a AZ

Public Subnet AZ2 is in us-east-1b AZ

Moving forward let’s enable the Auto assign IP settings for these 2 public subnets. This means that anytime you launch EC2 instance in these public subnets, those EC2 instances will be assigned a public IPv4 address.

Let’s select Public Subnet AZ1 click Actions and click Edit subnet settings

Under Edit subnet settings and Auto-assign IP settings check the Enable auto-assign public IPv4 address

Scroll all the way down and hit Save. We are going to do the same procedure for Public Subnet AZ2

Under Edit subnet settings and Auto-assign IP settings check the Enable auto-assign public IPv4 address and we are ready to Save

Next is we need to create a public route table. Based on our reference architecture, we will call this Public Route Table.

Let’s click Route tables on the left side. The route table that we see was set up when we created the VPC. This is the main route table and its private by default.

Click Create route table. We will call it Public Route Table. Make sure to select Dev VPC under VPC before clicking Create route table

We have successfully created our Public Route Table

Let’s add a public route to the route table. This will allow the route table to route traffic to the internet. First, let’s make sure that we are on the Routes tab then click Edit routes

Click Add route

To add a route that routes traffic to the internet to this route table, we will add 0.0.0.0/0 under Destination and the Target should be the Internet Gateway igw-0d4cf65f60faaed05. When this is all filled in we can click Save changes

We successfully added a route to the internet to our public route table. You can see it under the Routes tab

Let’s associate the 2 public subnets we created earlier with this route table. Let’s ensure that we are still under Public Route Table

Click Subnet associations and click Edit subnet associations. On this page, we can see the 2 subnets that we created previously

Under Edit subnet associations select both Subnets and Save association.

Good job! We have associated the 2 subnets that we created to the Public Route Table. These will now show under Subnet associations tab

To finish creating our VPC we need to create 4 private subnets. So let’s click Subnets at the left side and Create subnet

We will still stick to our Dev VPC under VPC ID and based on our reference architecture let’s name it Private App Subnet AZ1 and choose us-east-1a Availability Zone.

Our CIDR block should be 10.0.2.0/24 and we are now ready to Create subnet

There you go! We created our 1st private subnet in the us-east-1a Availability Zone. Doing the same procedures above let’s create the next 3 private subnets using the settings below and referring to our reference architecture:

2nd Subnet

VPC ID: Dev VPC

Subnet name: Private App Subnet AZ2

Availability Zone: us-east-1b

IPv4 CIDR block: 10.0.3.0/24

3rd Subnet

VPC ID: Dev VPC

Subnet name: Private Data Subnet AZ1

Availability Zone: us-east-1a

IPv4 CIDR block: 10.0.4.0/24

4th Subnet

VPC ID: Dev VPC

Subnet name: Private Data Subnet AZ2

Availability Zone: us-east-1b

IPv4 CIDR block: 10.0.5.0/24

We have successfully created all 4 subnets. To see these let’s click Clear filters and filter it by Dev VPC

Let’s also review and make sure that we put each subnets in the right availability zones.

Before we move on to Part 2 of our project, let’s discuss about an important thing.

Difference between public and private subnet

When we create a route table and add a route to that route table to route traffic to the internet, any subnet you associate with that route table becomes public.

Basically, a public subnet is associated with a route table that is able to route traffic to the internet.

On the other hand, when you have a route table that does not have a route to the internet, any subnet you associate with that route table is private.

To show you why these 2 subnets are public:

and these subnets are private

let’s look at the VPC we just created. To verify these, click on Route Tables and filter it by our VPC — Dev VPC

Let’s select Public Route Table and Routes tab, this route table is routing traffic to the internet. So any subnet we associate with this route table becomes public.

The Subnet associations tab shows that we associated both Public Subnet AZ1 and AZ2 to this route table. That is what makes these 2 subnets public.

On the other hand, let’s select the main Route Table. Uncheck the Public Route Table and select the main Route table — this was created when we created the VPC.

The main Route table is private by default it is only routing traffic locally in the VPC and it doesn’t have a route to the internet

Further, we created 4 private Subnets we did not associate them with any route tables. By default, they will be associated with the main Route table which is private. Going back to the main Route table under Subnet associations

Let’s scroll down to Subnets without explicit associations. It says The following subnets have not been explicitly associated with any route tables and are therefore associated with the main route table.

On the next part of our project, we will create a NAT Gateway and private Route tables. We will explicitly associate our private subnet with our private Route tables but for now we will let the Private subnet be associated with the main Route table which is private by default.

Part 2: Create NAT Gateways

NAT Gateway Reference Architecture

NAT Gateway Reference Architecture

  1. The NAT Gateway allows the instances in the private app subnets and private data subnets to access the internet
  2. The Private Route Table is associated with the private subnets and routes traffic to the internet through the NAT gateway.

We need to create a NAT gateway in the first and second availability zone using the reference architecture.

Let’s head to the Console Home and start, shall we?

Before creating the NAT Gateway let’s make sure that we are in the region where we created the VPC, hence N. Virginia us-east-1

Click VPC

Select NAT gateways

Click Create NAT gateway

We will create the first NAT gateway in the Public Subnet AZ1. We will call it NAT Gateway AZ1 and we will put this in the Public Subnet AZ1. We also need to click the Allocate Elastic IP button

Now we are ready to click Create NAT gateway. It should bring us to the NAT gateway created successfully page

Next is we need to create a route table. We will call it Private Route Table AZ1. Select Route tables at the left side and hit Create route table

We will call this Private Route Table AZ1 in Dev VPC then hit Create route table

The next page should say Route table was created successfully.

Let’s add a route to the Private Route Table AZ1 to route traffic to the internet through the NAT gateway in the Public Subnet AZ1

Under Routes tab click Edit routes then Add route

Internet traffic is always 0.0.0.0/0 so we will select that as our Destination

Our target will be NAT gateway and we need to select NAT gateway AZ1. We’re ready to click Save changes the next page shows Updated routes for Private Route Table AZ1 successfully

Great work! If we scroll down we can see the route here

Next we will associate Private Route Table AZ1 with Private App Subnet AZ1 and Private Data Subnet AZ1.

Let’s click the Subnet associations tab and Edit subnet associations

From the list of available subnets below we need to select Private App Subnet AZ1 and Private Data Subnet AZ1 then click Save associations

We have successfully associated Private App Subnet AZ1 and Private Data Subnet AZ1 to the Private Route Table AZ1 as shown under Explicit subnet associations

and Explicit subnet associations under Subnet associations tab

Now let’s create our second NAT gateway in the Public Subnet AZ2. The next steps are similar to what we did previously. Click NAT gateways at the left

Hit Create NAT gateway

These are the information that we need to put

Name: NAT Gateway AZ2

Subnet: Public Subnet AZ2

Elastic IP allocation ID: Allocate Elastic IP

We have successfully created our second NAT Gateway

Now let’s create another route table named — Private Route Table AZ2. Click Route Table at the left side

Click Create route table and here are the information that we need to in the Route table settings.

Name: Private Route Table AZ2

VPC: Dev VPC

Once all settings are complete click Create route table

Next is we will add a route to this route table to route traffic to the internet through the NAT gateway in the Public Subnet AZ2

Let’s click the Routes tab and Edit routes

Click Add route and enter the following information

Destination: 0.0.0.0/0

Target: Nat Gateway AZ2

Click the Save changes button and we have successfully updated routes for Private Route Table AZ2

Lastly, we need to associate this route table with Private App Subnet AZ2 and Private Data Subnet AZ2.

Let’s go to Subnet associations tab then click Edit subnet associations

We’re going to select Private App Subnet AZ2 and Private Data Subnet AZ2 then click Save associations

We have successfully updated the subnet associations for Private Route Table AZ2 as shown under Explicit subnet associations

It will also show under the Subnet associations tab then Explicit subnet associations

Good work! This is how we create NAT gateways to allow resources in the private subnet to have access to the internet.

Part 3: Create Security Groups

WordPress Security Group Reference Architecture

Security Group Reference Architecture

These are the security groups that we need for this project.

ALB Security Group

  • This is the security group that we will add to the application load balancer
  • Port: 80 and 443 with Source: 0.0.0/0

SSH Security Group

  • Remember when you create an SSH security group you should always limit the source to your IP address
  • This is the security group that we will use to SSH into our EC2 instance
  • Port: 22 with Source: Your IP Address

Webserver Security Group

  • This is the security group that we will add to the web servers in the private app subnets
  • Port: 80 and 443 with Source: ALB Security Group
  • Port: 22 with Source: SSH Security Group

Database Security Group

  • This is the security group that we will add to the RDS instance in the private data subnet
  • Port: 3306 Source: Webserver Security Group

EFS Security Group

  • This is the security group that we will add to the elastic file system
  • Port: 2049 Source: Webserver Security Group, EFS Security Group
  • Port: 22 Source: SSH Security Group

Let’s head over to the console and create the security groups. We will use the information from the reference architecture above.

In the console home click VPC

At the left hand side click security groups

Click create security group

Enter the following settings

Basic details

Security group name: ALB Security Group

Description: ALB Security Group

VPC: Dev VPC

Inbound rules — we will add 2 rules

1st rule

Type: HTTP

Protocol: TCP

Port range: 80

Source: 0.0.0.0/0

2nd rule

Type: HTTPS

Protocol: TCP

Port range: 443

Source: 0.0.0.0/0

Once we opened the ports let’s click Create security group

We successfully created the ALB security group

Let’s create the SSH security group. Click security groups to go back one directory

Click create security group and enter the following settings

Basic details

Security group name: SSH Security Group

Description: SSH Security Group

VPC: Dev VPC

Inbound rules

Type: SSH

Protocol: TCP

Port range: 22

Source: My IP

This is the only rule that we need to add to our SSH security group let’s click create security group

We successfully created the SSH security group

The next security group that we will create is web server security group. Click security groups to go back one directory

Click create security group

Click create security group and enter the following settings

Basic details

Security group name: Webserver Security Group

Description: Webserver Security Group

VPC: Dev VPC

Inbound rules

1st rule

Type: HTTP

Protocol: TCP

Port range: 80

Source: ALB Security Group — this is how we limit a traffic to a particular security group

2nd rule

Type: HTTPS

Protocol: TCP

Port range: 443 — this is an internet traffic that is encrypted

Source: ALB Security Group

3rd rule

Type: SSH

Protocol: TCP

Port range: 22

Source: SSH Security Group

This completes the rules that we need for our webserver security group. Click create security group.

We have successfully created the web server security group. We’ve opened port 22 and limited the source to the SSH security group. We also opened port 80 and 443 and limited the source to the application load balancer security group

Next is database security group. Enter the following information below then click Create security group

Basic details

Security group name: Database Security Group

Description: Database Security Group

VPC: Dev VPC

Inbound rules

Type: MYSQL/Aurora

Protocol: TCP

Port range: 3306

Source: Webserver Security Group

EFS security group is the last one that we are going to make. Enter the following information below then click Create security group

Basic details

Security group name: EFS Security Group

Description: EFS Security Group

VPC: Dev VPC

Inbound rules

1st rule

Type: NFS

Protocol: TCP

Port range: 2049

Source: Webserver Security Group

2nd rule

Type: SSH

Protocol: TCP

Port range: 22

Source: Webserver Security Group

We have successfully created the EFS security group. One more thing that we need to is to go to Edit inbound rules

We will add another rule for NFS and we’re going to limit the source to EFS security group. Click Save rules after putting the information in

Type: NFS

Protocol: TCP

Port range: 2049

Source: EFS Security Group

You can review your security groups by going to security groups page and filter it to your Dev VPC. These are all the security groups that we need for this project.

Part 4: Create the RDS Instance

WordPress RDS Reference Architecture

WordPress RDS Reference Architecture

We will create the RDS instance in the private data subnets. Let’s head over to the console, search RDS or select RDS in the Recently visited

Before we create the RDS instance in the private data subnets, the first thing that we need to create are the subnet groups — this allows us to specify which subnets we want to create our RDS database in.

Select Subnet groups and Create DB subnet group

Enter the following information and hit Create

Subnet group details

Name: Database subnets

Description: Database subnets

VPC: Dev VPC

Add subnets

Availability Zones: us-east-1a and us-east-1b

Subnets: subnet with CIDR block 10.0.5.0/24 and subnet with CIDR block 10.0.4.0/24

Let’s create the database. Select Database and click Create database

Enter the information below

Database creation method: Standard create

Engine options: MySQL

Engine Version: MySQL 5.7.37 or latest

Templates: Dev/Test

Availability and durability : Single DB instance

  • According to our reference architecture, we can create a standby database in the other AZ. If you want to create a standby database in another AZ, you can select the Multi-AZ DB instance. For this project, so it won’t cost us money we won’t create a standby database

Settings

DB instance identifier: type a name for your DB instance

Credentials Settings: Provide your master username, password, and confirm password

Instance configuration

DB instance class: Burstable classes (includes t classes)

  • select db.t2.micro

Include previous generation classes: enabled

Connectivity

Virtual private cloud (VPC): Dev VPC

DB subnet group: ensure that the 2 subnet group we created earlier are selected

VPC security group (firewall): Choose existing

Existing VPC security groups: Databse Security Group

Availability Zone: us-east-1b

  • This is where you choose the AZ you want to create the master database in

Database authentication: checked

Additional configuration

Specify your Initial database name

Scroll all the way down and click Create database. It will take a few minutes to create our RDS instance. Wait until the Status says Available

Once you’ve created your RDS instance, you won’t be able to see the password for the RDS instance in the management console. That is why it is important to save your credentials. You can click View credentials details above to view your credentials the last time.

Let’s go to DB identifier name

Under the Connectivity & security tab is where we will find the endpoint for our database. We will need this information when we connect our database to our EC2 instance. You will find more information about our database below the Configuration tab.

Well done! This is how we create an RDS instance with MYSQL engine.

Part 5: Create the Elastic File System (EFS)

Elastic File System (EFS) Reference Architecture

Elastic File System (EFS) Reference Architecture

  1. We are using Amazon EFS so that the webservers can have access to shared files
  2. The EFS mount targets are in each AZ in the VPC. The webservers will use the mount targets to connect to the EFS

We will create an elastic file system with mount targets the private data subnets in each AZ. The EFS will allow the webservers in the private app subnets to pull the application code and configuration files from the same location.

From the management console, head to EFS and click Create file system

Select Customize

Under File system settings, name your file system. We also need to uncheck Enable encryption of data at rest so we don’t get charged

Enter the information below for Tags then click Next

Tag key: Name

Tag value: Dev-EFS

Under Network access use the following information

VPC: Dev VPC

Under Mount targets we will select the subnet in each AZ we want to put our mount target in. We are using 2 AZ in this VPC.

In us-east-1a, the subnet we will put the mount target in is the private data AZ1 and we will choose EFS Security Group under Security Groups

For us-east-1b use the information below and hit Next

Subnet ID: Private Data Subnet AZ2

We’re going to leave the File system policy to default and click Next

Review the settings then click Create

We have successfully created the EFS.

If you want to find the information to mount your EFS, click the File system ID

Hit Attach. This is where you can find the information to mount the file system.

Keep it up! This is how we create an elastic file system

Photo by Nimi Diffa on Unsplash

Part 6: Create a Key Pair (Windows Users)

We will need a key pair for our project. Click here to view my tutorial on creating a key pair for windows user. When you are finished, we will go to part 7 of this project.

Part 7: Download Putty (Windows Users)

We will also need putty for our project. Click here to view my tutorial on downloading putty for windows user. When you are finished, we will go to part 8 of this project.

Part 8: Launch the Setup Server

Reference Architecture

I’m glad you were able to create your key pair and download putty. On this part of our project, we will launch the EC2 instance we will use to install wordpress in the public subnet AZ1.

To launch the EC2 instance, let’s go to the console. Either type EC2 in the search bar or select EC2 from your recently visited then select Launch instance

On the Launch an instance page, enter the information below

Name: Setup Server

Application and OS Images (AMI)

  • click Quick Start
  • select Amazon Linux 2 AMI Free tier

Instance type: t2.micro

Key pair (login): select your key pair

Network settings

  • click Edit
  • VPC: Dev VPC
  • Subnet: Public Subnet AZ1

Firewall (security groups)

  • Select existing security group
  • We will use 3 security groups: SSH, ALB, and Webserver Security Group
  • You can view them all by clicking the + icon

You can also view the summary of your instance at the right menu then let’s click Launch instance

We have successfully launched the EC2 instance. You can click the instance ID to view your instance. Wait until the Instance state says running and Status check shows Passed

This is all that we need to launch the EC2 instance that we will use to install wordpress. Let’s head over to part 9.

Part 9: SSH Into an EC2 Instance in the Public Subnet (Windows Users)

To SSH into the setup server using putty let’s select Setup Server from the Instances page

Copy the public IPv4 address

Open Putty. Under Session, type the Host Name: ec2-user@the public IPv4 address you just copied

Under Connection, click the + sign under SSH

Select the + sign under Auth. Under Auth select Credentials

Below Private key file for authentication, click Browse

Browse to the location where you saved your private key and click Open

We are now ready to click Open. The first time you SSH into an EC2 instance you will see a prompt box, just click Accept

We have successfully SSH into our EC2 instance using putty. Let’s head over to the next part of our project

Part 10: Install WordPress

Once you have SSH into your setup server, we are going run several commands to install our wordpess site and move the file to the EFS.

Let’s open our putty session again. The first command we will run will create the HTML directory and mount the EFS to it.

Before we run this command, the first thing that we need to do is to update the mount information of our EFS.

Let’s go the console and open a new tab. Go to EFS and select your EFS ID then click Attach

Copy the information below

Replace command from fs upto .com with the command that we copied then copy all the 1st command

Paste in our putty session and it will start running the command and we will wait for the shell prompt to be available, this would mean the our EFS is alreay mounted

Let’s clear our screen and check if our EFS is mounted. Type df -h and press enter. You will see the information of your file system here and it is mounted to the html directory

Next, let’s install the apache web server. Let’s copy all the commands in #2 and paste it in our putty session. Wait until the shell prompt is available

sudo yum install -y httpd httpd-tools mod_ssl
sudo systemctl enable httpd
sudo systemctl start httpd

Type clear again to clear our screen. The next command we will run will install php version 7.4.

sudo amazon-linux-extras enable php7.4
sudo yum clean metadata
sudo yum install php php-common php-pear -y
sudo yum install php-{cgi,curl,mbstring,gd,mysqlnd,gettext,json,xml,fpm,intl,zip} -y

We have successfully installed php version 7.4

Up next is we’re going to install mysql version 5.7. Let’s copy and paste the command below

sudo rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo yum install mysql-community-server -y
sudo systemctl enable mysqld
sudo systemctl start mysqld

Successfully installed mysql version 5.7 good work!

This next command will set permissions on our web files

sudo usermod -a -G apache ec2-user
sudo chown -R ec2-user:apache /var/www
sudo chmod 2775 /var/www && find /var/www -type d -exec sudo chmod 2775 {} \;
sudo find /var/www -type f -exec sudo chmod 0664 {} \;
chown apache:apache -R /var/www/html

The permissions are now set

Command #6 will download wordpress and move the files to the html directory

wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz
cp -r wordpress/* /var/www/html/

We did it let’s clear the screen again

The next command will create the wp-config.php file

cp /var/www/html/wp-config-sample.php /var/www/html/wp-config.php

Once we created the wp-config.php file, we will edit it to enter the information of our RDS instance. The next command will open the nano text editor on our EC2 instance and we will edit our RDS information in there.

nano /var/www/html/wp-config.php
Nano text editor

In here, we will enter the information of our RDS database. Press the down arrow or your mouse key until you reach this

We will replace this information with the name of our database

Let’s go to the console and go to RDS. Let’s select DB instances

Let’s select our RDS instance

Under configuration tab, let’s copy the DB name

Paste between the quotation mark in the nano text editor

Next is we need to put the user name between the quotation mark here

To get the DB username let’s go back to the configuration tab and copy the DB username

Paste it here

Next is we need to put our database password here

Afterwards, the database hostname will be the endpoint of our RDS instance. To get the hostname, let’s head to Connectivity & security tab adn copy the Endpoint

Paste it between the quotation marks under Database hostname

These are all the information that our EC2 instance needs to connect to the RDS instance. Let’s hit these keys on our keyboard

Ctrl + X then press Y and Enter. We have successfully the wpconfig file to enter the information of our RDS database

The last command that we need to run will restart our web server

service httpd restart

After restarting the web server, let’s go to the EC2 dashboard and copy the Public IPv4 address

Open a window and paste the public IPv4 address in the address bar

Well done! We have successfully configured our wordpress site. We are going to finish the installation here as well. Provide you preferred information below and click Install WordPress

Good work! WordPress has been installed successfully

Let’s log in to the website using your credentials

We have successfully installed our wordpress website and moved the files to the EFS! We still need our setup server to create an application load balancer to route traffic to the EC2 instance in the private subnet

Part 11: Create an Application Load Balancer

Reference Architecture

Reference Architecture

  1. We are using EC2 Instance to host our website
  2. Application Load Balancer is used to distribute web traffic across EC2 instances in multiple AZs

Welcome to part 11 of our project. Before we create an ALB, first we will launch an EC2 instance in each of the private app subnet.

Let’s click Launch instance and enter the information below

Name: Webserver AZ1

AMI: Amazon Linux 2 AMI

Instance type: t2.micro

Key pair: select your keypair

Network settings

VPC: Dev VPC

Subnet: Private App Subnet AZ1

Security groups: Webserver Security Group

User data — the following command means that when the EC2 instances are coming online, it will run these commands for us. Looking at the commands closely, these are the same commands we ran on the setup server to install apache, php ver. 7.4, and mysql.

Before we can run wordpress on our EC2 instance, first we need to make sure that apache webserver, php, and mysql are installed on the EC2 instance.

These are commands that we need for our user data

#!/bin/bash
yum update -y
sudo yum install -y httpd httpd-tools mod_ssl
sudo systemctl enable httpd
sudo systemctl start httpd
sudo amazon-linux-extras enable php7.4
sudo yum clean metadata
sudo yum install php php-common php-pear -y
sudo yum install php-{cgi,curl,mbstring,gd,mysqlnd,gettext,json,xml,fpm,intl,zip} -y
sudo rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo yum install mysql-community-server -y
sudo systemctl enable mysqld
sudo systemctl start mysqld
echo "fs-03c9b3354880b36a6.efs.us-east-1.amazonaws.com:/ /var/www/html nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0" >> /etc/fstab
mount -a
chown apache:apache -R /var/www/html
sudo service httpd restart

Let’s update the EFS information by going to the EFS dashboard. Select your EFS ID and hit Attach

Copy the information below

Update the EFS information in the commands

echo "fs-0220d0af438f49b6f.efs.us-east-1.amazonaws.com:/ /var/www/html nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0" >> /etc/fstab
mount -a

Now we are ready to paste these commands in the User data box

Let’s review the Settings of our instance and click Launch instance

Let’s launch our 2nd instance in the private app subnet AZ2. Let’s go back to the EC2 dashboard and click Launch instance

Enter the information below

Name: Webserver AZ2

AMI: Amazon Linux 2 AMI

Instance type: t2.micro

Key pair: select your keypair

Network settings

VPC: Dev VPC

Subnet: Private App Subnet AZ2

Security group: Webserver Security Group

Enter the same command in the User data

#!/bin/bash
yum update -y
sudo yum install -y httpd httpd-tools mod_ssl
sudo systemctl enable httpd
sudo systemctl start httpd
sudo amazon-linux-extras enable php7.4
sudo yum clean metadata
sudo yum install php php-common php-pear -y
sudo yum install php-{cgi,curl,mbstring,gd,mysqlnd,gettext,json,xml,fpm,intl,zip} -y
sudo rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo yum install mysql-community-server -y
sudo systemctl enable mysqld
sudo systemctl start mysqld
echo "fs-0220d0af438f49b6f.efs.us-east-1.amazonaws.com:/ /var/www/html nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0" >> /etc/fstab
mount -a
chown apache:apache -R /var/www/html
sudo service httpd restart

Reveiw the settings and hit Launch instance

Let’s view our instances. We have successfully launched our 2 instances in the private app subnet AZ1 and private app subnet AZ2

Let’s create a target group then we will put these instances in the target group to allow the ALB to route traffic to them.

Click Target group at the left hand side

Enter the information below and click Next

Target type: Instances

Target group name: Dev-TG

Protocol: HTTP

VPC: Dev VPC

Advanced health check settings

Success codes: 200,301,302

On this page, we will select the instances we want the ALB to route traffic to. Pick Webserver AZ1 and Webserver AZ2 then click Include as pending below

Click Create target group

We have Successfully created target group. The next step is we will create the ALB. At the left side select Load Balancers then Create load balancer

It’s going to be Application Load Balancer and hit Create

Let’s enter the information below

Load balancer name: Dev-ALB

Scheme: Internet-facing

IP address type: IPv4

VPC: Dev VPC

Under Mappings, we have to select at least 1 public subnet in each AZ for the ALB. First, let’s choose us-east-1a and select Public Subnet AZ1. Second, let’s select us-east-1b and choose Public Subnet AZ2

Under Security groups, remove the default and select the ALB Security Group

We will set up a listener of port 80. Under Listener and Default action, we will select Dev-TG (this is the target group we created earlier). We will set up an HTTPS listener later.

Let’s click Create load balancer and we should get a successful prompt. Click View load balancer

We will wait for its State to be Active

We will use the DNS name of the ALB to access our website

Open a new tab, paste the DNS name in the address bar and hit enter

We can now access the website using the DNS name of our application load balancer. One more step that we need to do, anytime you change your domain address, you have to go to your wordpress settings and change your domain address there as well.

To change the domain settings in our wordpress configuration file, copy the domain name from the address bar

add /wp-admin to your DNS name, press enter, and it will bring us to this page

Log in so that it brings us to the wordpress dashboard again.

Go to Settings and General

Update the WordPress Address and Site Address URL with the DNS name you copied make sure there is no / at the end then Save Changes

Let’s log back in to the wordpress dashboard. Now that we have launched 2 EC2 instances in the private app subnet and we can access our website using the DNS of our ALB, go ahead and terminate your Setup server by going to your EC2 dashboard.

This is how you create an ALB to route traffic to the EC2 instances in the private subnet. You are doing very well let’s head over to the next step.

Part 12: Register a New Domain Name in Route 53

We will register a new domain name in Route 53. This will allow our end users to access our website using that domain name instead of the DNS name of our application load balancer. View my previous tutorial here. Once you completed it we will go to the next part of this project.

Part 13: Create a Record Set in Route 53

We will create a record set in Route 53 to access our website using our domain name.

To create a record set in Route 53, go to the Route 53 dashboard

Select Hosted zones and click your Domain

Click Create record

Enter the information below then hit Create records

Record name: www

Route traffic to:

  • Alias to Application and Classic Load Balancer
  • US East (N. Virginia) [us-east-1]
  • Dev-ALB

We have successfully created a record set

Select our Record name and copy the Record name to your right

Open a new tab and paste the record name in the address bar. We can now access our website using the domain name.

If you recall what we discussed previously, every time the domain name changed, you have to go your wordpress settings and change your domain name as well.

Copy your domain name in the address bar

add /wp-admin

Log in to your wordpress site

If you noticed, this wordpress site is still pointing to the ALB’s DNS name so we are going to change it to our domain name.

Go to Settings then General

Update the WordPress Address (URL) and Site Address (URL) make sure there’s no forward slash at the end and Save Changes

Let’s log back in

When you are logged back in to the wordpress website, you will see that your site URL is now your domain name. Well done! This is how we create a record set in Route 53 to access our website using our domain name.

Part 14: Register for an SSL Certificate in AWS Certificate Manager

We will register for a free SSL certificate from the AWS certificate manager. We will use this to encrypt the communications between the web browser and our web servers.

For our website above, the communication between the web browser and our website is not secure. We will use this SSL certificate to secure all communications between the web browser and our website — also referred to as encryption in transit.

Go to AWS Certificate Manager and Request a certificate

Choose Request a public certificate under Certificate type

Enter your domain name and click Add another name to this certificate

In the second certificate box, we are going to add a wildcard. Type *. followed by your domain name. We will leave the rest to their default settings then click Request

Let’s View certificate after creating the request

If your status says Pending validation this means you need to create a record set in Route 53 to validate that this domain name belongs to you.

Just simply Create records in Route 53

Select the domain name you are creating the record set for in Route 53. So ensure that you selected your domain name and the wildcard then Create record

You will see that the Status of the Certificate is Issued. For the 2 domain names we requested the certificate for is now showing Success.

Good work! This is how you request a free certificate from AWS Certificate Manager.

Part 15: Launch Bastion Host

  1. To SSH into the instances in the private subnet:
  • we will launch an EC2 instance in the public subnet — we call this EC2 instance bastion host or jump box
  • Next we will SSH in the instance we launched in the public subnet
  • Lastly, from the instance in the public subnet, we can SSH into any instance in the private subnets

To launch the bastion host in the public subnet, click Launch instance from the EC2 Dashboard and enter the information below. Review the Summary and click Launch instance

Name: Bastion Host

AMI: Amazon Linux 2

Instance type: t2.micro

Key pair: Select your key pair

VPC: Dev VPC

Subnet: Public Subnet AZ1

Security Group: SSH Security Group

We have successfully launched our Bastion Host instance. Wait until the Instance state says Running and Status check 2/2 passed. Let’s go the next part of our project!

Please Note: Using Systems Manager is a great alternative to connecting via SSH or using a Bastion host. It provides secure and direct access to instances without the need for opening ports or exposing your local machine to potential security risks.

Photo by Jonathan Chng on Unsplash

Part 16: SSH into an EC2 Instance in the Private Subnet (Windows Users)

Now that we have launch our EC2 instance in the public subnet, we will download Pageant in our computer.

Go to putty by greenend.org.uk and select Download it here

Under Alternative binary files, select the version of your pageant and download the file it should go straight to your download folder or other folder where you set the destination of your downloads

You will see the icon at the bottom right part of your screen after downloading it

Open the pageant. We will add the key pair we used to SSH into our EC2 instance into pageant. Click Add Key

Locate where you saved your key pair and hit Open

We added the key pair. You can Close this window. That’s all we need to do to add the key. We can now SSH into the EC2 instance in the private subnet.

Going back to EC2 dashboard, we will SSH into the instance we launched in the public subnet. Select the Bastion Host instance and copy the Public IPv4 address

Open putty and enter our host name ec2-user@ followed by the public IPv4 address of the instance we launched in the public subnet

Go to SSH > Auth > Allow agent forwarding then click Open

Click Accept on the Putty Security Alert

We have successfully SSH into the EC2 instance in the public subnet. You can tell because the IP address in our putty session is the same as the IP address f the bastion host. We can now SSH into the EC2 instance in the private subnet

To do this, enter ssh ec2-user@ followed by the Private IPv4 address of your Webserver AZ1

The first time doing this, it will ask you this question, just type yes and press enter

We successfully SSH into the EC2 instance in the private subnet. You can tell this because the IP address highlighted in the putty session is the same as the Private IPv4 addresses of Webserver AZ1.

Part 17: Create an HTTPS Listener for the Application Load Balancer

We’re going to create an HTTPS listener for our ALB to secure our website. Let’s go to the EC2 dashboard and head over to Load balancer

Ensure that your load balancer name is selected then click the Listener tab then Click Add listener

Switch the protocol to HTTPS this is always on port 443

Select Forward under Default actions

Target group will be Dev-TG

Select your Default SSL/TLS certificate and click Add at the bottom right part of your screen

The HTTPS listener is added. Let’s edit the HTTP listener to redirect HTTP traffic to HTTPS

Select the HTTP listener and Edit

Remove the Default actions

Select Redirect under Default actions

We are going to redirect it to HTTPS and enter Port 443. Save changes

We have successfully edited our HTTP listener to redirect traffic to HTTPS.

To make sure that our website is secure, the next thing that we need to do is to SSH into one of our webservers in the private app subnet. The photo above shows that we have successfully SSH into the webserver AZ1.

Clear the screen afterwards

Type sudo su to change to root

Next, let’s enter nano /var/www/html/wp-config.php

This brings us to nano text editor

Using the arrow key, go down up to this row and press Enter twice

Move your arrow up once

/* SSL Settings */
define('FORCE_SSL_ADMIN', true);

// Get true SSL status from AWS load balancer
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = '1';
}

Enter these commands

Ensure that the commands are entered correctly as I did mine then press Ctrl + X, press Y and press Enter

Bringing us to this page. Once we edited the wpconfig file and added the code, let’s go to our website to see if our website is secure

Good job! We can access our website and the connection to our website is secure. Let’s update the URL settings for our wordpress site. Copy the domain name in the address bar

Add /wp-admin

Once we are logged in to our wordpress website, go to Settings > General

Let’s update these http URL to our DNS

After we updated our URL make sure we remove forward slash at the end. Scroll all the way down and Save Changes

To verify if everything is working fine, let’s log back in to our wordpress site

We are able to log in to the wordpress website and its secure. This is how we create an HTTPS listener for our website

Part 18: Create an Auto Scaling Group

Reference Architecture

We will create an auto scaling group to dynamically create and scale the web servers in the private app subnet.

First we need to terminate the EC2 instances we manually created. Head over to Instance running under EC2 Dashboard. Select both Webserver AZ1 and Webserver AZ2, click Instance state and Terminate

These instances are terminating. Next, we need to create our Launch templates — this contains the configuration of the EC2 instance that auto scaling group will use to launch new EC2 instances

Go to Launch Templates > Create launch template

Enter these information

Launch template name: Dev-Launch-Template

Template version description: Launch Template for ASG

Provide guidance to help me set up a template that I can use with EC2 Auto Scaling: Checked

Application and OS Images: Amazon Linux 2 AMI

Instance type: t2.micro

Keypair: select your key pair

Select existing group and let’s choose Webserver Security Group

#!/bin/bash
yum update -y
sudo yum install -y httpd httpd-tools mod_ssl
sudo systemctl enable httpd
sudo systemctl start httpd
sudo amazon-linux-extras enable php7.4
sudo yum clean metadata
sudo yum install php php-common php-pear -y
sudo yum install php-{cgi,curl,mbstring,gd,mysqlnd,gettext,json,xml,fpm,intl,zip} -y
sudo rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo yum install mysql-community-server -y
sudo systemctl enable mysqld
sudo systemctl start mysqld
echo "fs-0220d0af438f49b6f.efs.us-east-1.amazonaws.com:/ /var/www/html nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0" >> /etc/fstab
mount -a
chown apache:apache -R /var/www/html
sudo service httpd restart

The command above, update the EFS file (from ‘fs’ to ‘.com’) with the information from your EFS file system

In User data under Advance details, paste all the commands and hit Create launch template

We created the launch template. Let’s go ahead and create our auto scaling group

Let’s go to Create Auto Scaling group

Give your ASG a name and select the launch template we created previously then click Next

VPC: Dev VPC

Availability Zones and subnets: Private App Subnet AZ1 and Private App Subnet AZ2

Let’s make sure that we enter these information correctly before clicking Next

Under Load balancing, we are going to attach our auto scaling group with the ALB we created previously

Select these information under Load balancing

  • Attach to an existing load balancer
  • Choose from your load balancer target groups

Existing load balancer target groups: select your target group

Enable Turn on Elastic Load Balancing health checks and Enable group metrics collection within CloudWatch then click Next

We want our auto scaling group to maintain two EC2 instances and the ASG can scale down to a minimum 1 instance or a maximum of 4 instances, click Next

Add notification

Select the cloudwatch topic we created earlier. If you don’t have it already you can click Create a topic. Leave all Event types checked and click Next

Let’s add a tag. Provide Key and Value then click Next. Verify your settings and Create Auto Scaling group

We successfully created our auto scaling group with desired capacity of 2

You should have 2 instances running. These were launched by the ASG. You can tell because these are the tag names we gave them (ASG-Webserver). Let’s wait until it pass the Status check

Let’s also make sure that the Health status of the Registered targets are healthy. We do this by going to Target Groups under Load Balancing

Type your domain name and press enter. This is how you create an auto scaling group to dynamically create and scale the EC2 instances in the private app subnet

Part 19: Install WordPress Theme and Template

Let’s install themes and template for our website to make it look presentable

Log in as admin to your wordpress website and add /wp-admin after your domain and press enter

Click on Appearance then Themes

Click Add New

Install the Astra theme and Activate

Click Get started to install the template

On this page, click Build Your Website Now

Choose Elementor

You can search any templates for your website. In my case I am choosing Pets

Just click Skip and Continue

Enter your information and click Submit & Build My Website

Select View Your Website and give it time to load

There you have it, you can see our website here. Once you have created all the resources in AWS for your wordpress website, we will install a template for it.

This is a great project you can present during your interviews s one of the projects you worked on.

Let’s log out of the website as the admin. We are going to access our website the same way end users would access it. Go ahead and type your domain name in the address bar.

This is how you host a website in AWS

Clean up

Don’t forget to clean up your AWS accounts so it won’t incur costs. These are the accounts/resources that you need to clean

  1. Auto scaling group
  2. Launch template
  3. Application load balancer
  4. Target group
  5. RDS instance
  6. Bastion host
  7. EFS
  8. Security groups
  9. NAT gateway
  10. VPC
  11. Elastic IP
  12. Record set
Photo by Eilis Garvey on Unsplash

Congratulations! Thank you for completing this project with me. Let me know if you have any questions and I look forward to see you on my next project.

Build real-world projects with me here! Show your employers that you are the right person for the job and stand out from the crowd!

Connect with me on LinkedIn

--

--

Eugene Miguel

Cloud DevOps Engineer • AWS Certified Solutions Architect