Deploy a WordPress Website on AWS
I will walk you through deploying a WordPress website on AWS using the management console
Requirements
- AWS Certified Cloud Practitioner CLF-C01
- AWS Certified Solutions Architect Associate SAA-C03
- 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
- Build a three-tier AWS network VPC from scratch
- Create NAT gateways
- Create the security groups
- Create the RDS instance
- Create the elastic file system
- Create a key pair
- Download putty
- Launch the setup server
- SSH into an EC2 instance in the public subnet
- Create an application load balancer
- Register a new domain name in Route 53
- Create a record set in route 53
- Register for an SSL certificate in AWS certificate manager
- Launch bastion host
- SSH into an instance in the private subnet
- Create an HTTPS listener for the application load balancer
- Create an auto scaling group
- Install WordPress theme and template
- Clean up
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
- VPC with public and private subnets in 2 availability zones
- An internet gateway is used to allow communication between instances in VPC and the internet
- We are using 2 availability zones for high availability and fault tolerance
- Resources such as NAT gateway, bastion host, and application load balancer use public subnets.
- We will put the web servers and database servers in the private subnets to protect them
- The public route table is associated with the public subnets and routes traffic to the internet through the internet gateway
- 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
- The NAT Gateway allows the instances in the private app subnets and private data subnets to access the internet
- 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
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
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
- We are using Amazon EFS so that the webservers can have access to shared files
- 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
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
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
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
- We are using EC2 Instance to host our website
- 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
- 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.
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
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
- Auto scaling group
- Launch template
- Application load balancer
- Target group
- RDS instance
- Bastion host
- EFS
- Security groups
- NAT gateway
- VPC
- Elastic IP
- Record set
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