IMPLEMENTING A THREE-TIER WEB SOLUTION WITH WORDPRESS
In this project, I will present a step-by-step guide to preparing storage infrastructure on two Linux servers and implementing a basic web solution using WordPress. You will have the hands-on experience that showcases Three-tier Architecture while also ensuring that the disks used to store files on the Linux servers are adequately partitioned and managed through programs such as gdisk
and LVM
respectively.
WordPress is a free and open-source content management system written in PHP and paired with MySQL or MariaDB as its backend relational database management system (RDBMS).
Three-tier Architecture
Generally, web or mobile solutions are implemented based on what is called the "three-tier architecture."
Three-tier architecture is a client-server software architecture pattern that comprises three separate layers.
- Presentation Layer (PL): This is the user interface such as the client-server or browser on your laptop.
- Business Layer (BL): This is the backend program that implements business logic. Application or Webserver
- Data Access or Management Layer (DAL): This is the layer for computer data storage and data access. Database Server or File System Server such as FTP server, or NFS Server
In this project,
- A laptop or PC will server as the client
- A RHEL EC2 instance will serve as the web server (WordPress will be installed on this server).
- A RHEL EC2 instance will server as the db-server.
LAUNCH AN EC2 INSTANCE THAT WILL SERVE AS “WEB SERVER AND APP SERVER”
Step 1: Create and configure two Linux-based virtual servers (EC2 instances in AWS). This involves creating two security groups that allow SSH connections on port 22. These instances will be launched in the default VPC. This can be done using the below commands:
SG for DB-Server
aws ec2 create-security-group --group-name DBSG \
--description "Security group for 3-tier webapp project" \
--vpc-id vpc-0344c69 \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=DBSG}]' \
--query 'GroupId' --output text \
| xargs -I {} aws ec2 authorize-security-group-ingress --group-id {} \
--protocol tcp --port 22 --cidr 0.0.0.0/0
SG for App-server
aws ec2 create-security-group --group-name AppSG \
--description "Security group for 3-tier webapp project" \
--vpc-id vpc-0344c....6086 \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=AppSG}]' \
--query 'GroupId' --output text \
| xargs -I {} aws ec2 authorize-security-group-ingress --group-id {} \
--protocol tcp --port 22 --cidr 0.0.0.0/0
Launch the client and server EC2 instances
Launch two RHEL EC2 instances that will serve as “Web Server” and “App-Server” respectively. For each of these instances, create three volumes in the same AZ as your EC2 instance, each of 10 GB.
# Launch App-Server EC2 Instance
aws ec2 run-instances --image-id ami-08d9.....e5c2 \
--count 1 \
--instance-type t2.micro \
--key-name <Key Pair> \
--security-group-ids sg-0be.....d0d \
--subnet-id subnet-0ef.....14b4 \
--block-device-mappings "[{\"DeviceName\":\"/dev/sdf\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}},{\"DeviceName\":\"/dev/sdg\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}},{\"DeviceName\":\"/dev/sdh\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}}]" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=App-Server}]' 'ResourceType=volume,Tags=[{Key=Name,Value=App-Server-disk}]'
# Launch DB-Server EC2 Instance
aws ec2 run-instances --image-id ami-08d9.....e5c2 \
--count 1 \
--instance-type t2.micro \
--key-name <Key Pair> \
--security-group-ids sg-0be.....hgd00 \
--subnet-id subnet-0ef.....14b4 \
--block-device-mappings "[{\"DeviceName\":\"/dev/sdf\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}},{\"DeviceName\":\"/dev/sdg\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}},{\"DeviceName\":\"/dev/sdh\",\"Ebs\":{\"VolumeSize\":10,\"DeleteOnTermination\":false}}]" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=DB-Server}]' 'ResourceType=volume,Tags=[{Key=Name,Value=DB-Server-disk}]'
Step 2: Configure the App and DB Servers
- Open up the terminal of the app server to begin configuration.
- Use
lsblk
command to inspect what block devices are attached to the server. Notice names of your newly created devices. All devices in Linux reside in /dev/ directory. Inspect it withls /dev/
and make sure you see all 3 newly created block devices there – their names will likely bexvdf
,xvdh
,xvdg
.
3. Use df -h
command to see all mounts and free space on your server
4. Use gdisk
utility to create a single partition on each of the 3 disks by running the below command to open up an interactive shell and responding to the prompts as follow:
sudo gdisk /dev/xvdf
sudo gdisk /dev/xvdh
sudo gdisk /dev/xvdg
a. Enter “n” to create a new partition, press “Enter” to accept the default Partition number (i.e., Partition number 1), or enter your preferred partition number, Select the size of the First sector (press Enter to accept the default of 2048GB) and press Enter to assign the remaining free space to the Last sector. Enter the Hexadecimal code of the volume (i.e., enter 8300 to select the Linux Filesystem)
b. Enter “p” to print out the partition table.
c. Enter “w” to write the disk.
d. Enter “yes” to save this change and exit the interactive shell.
5. Install lvm2
package using sudo yum install lvm2 -y
. Run sudo lvmdiskscan
command to check for available partitions.
6. Use pvcreate
utility to mark each of 3 disks as physical volumes (PVs) to be used by LVM
sudo pvcreate /dev/xvdf1
sudo pvcreate /dev/xvdg1
sudo pvcreate /dev/xvdh1
7. Verify that your Physical volume has been created successfully by running sudo pvs
8. Use vgcreate
utility to add all 3 PVs to a volume group (VG). Name the VG webdata-vg and Verify that your VG has been created successfully by running sudo vgs
sudo vgcreate webdata-vg /dev/xvdh1 /dev/xvdg1 /dev/xvdf1
9. Use lvcreate
utility to create 2 logical volumes. apps-lv (Use half of the PV size), and logs-lv Use the remaining space of the PV size. NOTE: apps-lv will be used to store data for the Website while, logs-lv will be used to store data for logs.
sudo lvcreate -n apps-lv -L 14G webdata-vg
sudo lvcreate -n logs-lv -L 14G webdata-vg
10. Verify that your Logical Volume has been created successfully by running sudo lvs
11. Verify the entire setup
sudo vgdisplay -v #view complete setup - VG, PV, and LV
sudo lsblk
12. Use mkfs.ext4
to format the logical volumes with ext4 filesystem
sudo mkfs -t ext4 /dev/webdata-vg/apps-lv
sudo mkfs -t ext4 /dev/webdata-vg/logs-lv
13. Create /var/www/html directory to store website files and Create /home/recovery/logs to store backup of log data
# Create directory to store website files
sudo mkdir -p /var/www/html
# Create directory to store backup of log data
sudo mkdir -p /home/recovery/logs
14. Mount /var/www/html on apps-lv logical volume
sudo mount /dev/webdata-vg/apps-lv /var/www/html/
15. Use rsync
utility to backup all the files in the log directory /var/log into /home/recovery/logs (This is required before mounting the file system)
sudo rsync -av /var/log/. /home/recovery/logs/
16. Mount /var/log on logs-lv logical volume. (Note that all the existing data on /var/log will be deleted. That is why step 15 above is very important)
sudo mount /dev/webdata-vg/logs-lv /var/log
17. Restore log files back into /var/log directory
sudo rsync -av /home/recovery/logs/. /var/log
Run “sudo lsblk” to see the present setup
18. Update /etc/fstab
file so that the mount configuration will persist after restart of the server. To do this, first run “sudo blkid” to get the UUID of the logical volume and add these to the /etc/fstab/ file as follow:
19. Test the configuration and reload the daemon
sudo mount -a
sudo systemctl daemon-reload
20. Verify your setup by running df -h
, output must look like this:
Step 3: Prepare the Database Server
Ssh into the db-server and repeat the same steps as for the Web Server, but instead of apps-lv
create db-lv
and mount it to /db
directory instead of /var/www/html/
.
Edit /etc/fstab file and verify setup by running “df -h”
Step 4: Install WordPress on your Web Server EC2
We will be installing wget, httpd, php, php-mysqlnd, php-fpm, and php-json.
# Update the repository
sudo yum -y update
# Install wget, Apache and it’s dependencies
sudo yum -y install wget httpd php php-mysqlnd php-fpm php-json
# Start Apache
sudo systemctl enable httpd
sudo systemctl start httpd
# Install PHP and its Dependencies
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo yum install yum-utils http://rpms.remirepo.net/enterprise/remi-release-8.rpm
sudo yum module list php
sudo yum module reset php
sudo yum module enable php:remi-7.4
sudo yum install php php-opcache php-gd php-curl php-mysqlnd
sudo systemctl start php-fpm
sudo systemctl enable php-fpm
sudo setsebool -P httpd_execmem 1
Restart Apache server
sudo systemctl restart httpd
Create a new directory called “wordpress”, change to this directory, Download WordPress, extract the contents of the zip file and copy wordpress to var/www/html.
mkdir wordpress
cd wordpress
sudo wget http://wordpress.org/latest.tar.gz
sudo tar xzvf latest.tar.gz
sudo rm -rf latest.tar.gz
sudo cp wordpress/wp-config-sample.php wordpress/wp-config.php
sudo cp -R wordpress /var/www/html/
Configure SELinux Policies. SELinux (Security-Enhanced Linux) is a security mechanism implemented in the Linux kernel to provide mandatory access control (MAC) for the system. SELinux policies define how processes and users can access various system resources such as files, directories, and ports.
sudo chown -R apache:apache /var/www/html/wordpress
sudo chcon -t httpd_sys_rw_content_t /var/www/html/wordpress -R
sudo setsebool -P httpd_can_network_connect=1
Step 5: Install MySQL on your DB Server EC2
Update the server and install mysql-server and verify that the MySQL service is running.
sudo yum update -y
sudo yum install mysql-server -y
sudo systemctl restart mysqld
sudo systemctl enable mysqld
sudo systemctl start mysqld
Step 6: Configure DB to work with WordPress
login to MySQL and create a database called “wordpress” and also create a new user called “wordpress”. The host address of this user should be the private IP address of the web-server. This is the user which worpress would use to remotely access the db-server.
sudo mysql
CREATE DATABASE wordpress;
CREATE USER 'myuser'@'172.31.37.194' IDENTIFIED BY 'Password@123';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'172.31.37.194' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SHOW DATABASES;
exit
Step 7: Configure WordPress to connect to the remote database.
- Open MySQL Port 3306 on the DB-server EC2 to allow traffic between the App-server and DB-server. For extra security, we will only be allowing the IP address of the App-server.
2. Install MySQL client on the web-server and test that you can connect from your Web Server to your DB server by using mysql-client
sudo yum install mysql -y
sudo mysql -u wordpress -p -h 172.31.35.54
3. Change permissions and configuration so Apache can use WordPress:
Go to https://api.wordpress.org/secret-key/1.1/salt/ to generate new Authentication unique keys and salts, and update the /wordpress/wp-config.php file with these keys and the username, database, and password Wordpress would use to access the database.
sudo vi /var/www/html/wordpress/wp-config.php
4. Restart the webserver to apply the changes made to the wp-config file
sudo systemctl restart httpd
4. Enable TCP port 80 in Inbound Rules configuration for your Web Server EC2 (enable from everywhere 0.0.0.0/0 or from your workstation’s IP)
5. Try to access from your browser the link to your WordPress : http://13.42.46.226/wordpress/ and install it.
Login to Wordpress
Verify that the database connection is okay. On the menu bar, click on “Tools” , then “Site Health”, and on the top of the page, click on “info”. If the test show “Good” then the connection is okay.
Conclusion
We have successfully gone through the steps for configuring Linux storage system and have also deployed a full-scale Web Solution using WordPress CMS and MySQL RDBMS!
Credit