# LAMP Stack

LAMP is the fluorescent lightbulb of the internet. It’s utilitarian and does its job well, even if it doesn’t have the glow of an incandescent light nor the novelty of an LED bulb.

A huge portion of the internet is brought to you by open-source software. One of those programming languages is something that is used by nearly 80 percent of sites on the internet, and a huge chunk of the people using that programming language on their server are using three key tools—the operating system Linux, the HTTP server Apache, and the database system MySQL. Together these tools combined with PHP into one of the greatest killer apps the open-source community ever produced: the LAMP stack. (Get it?)


![visual-representation-of-the-lamp-stack-pnap.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1645135414855/FO2shlOZp.png)

**Linux**: The operating system (OS) makes up our first layer. Linux sets the foundation for the stack model. All other layers run on top of this layer.

**Apache**: The second layer consists of web server software, typically Apache Web Server. This layer resides on top of the Linux layer. Web servers are responsible for translating from web browsers to their correct website.

**MySQL**: Our third layer is where databases live. MySQL stores details that can be queried by scripting to construct a website. MySQL usually sits on top of the Linux layer alongside Apache/layer 2. In high end configurations, MySQL can be off loaded to a separate host server.

**PHP**: Sitting on top of them all is our fourth and final layer. The scripting layer consists of PHP and/or other similar web programming languages. Websites and Web Applications run within this layer.

Five popular web tools that use or have used LAMP and PHP

•	WordPress
•	Facebook
•	Wikipedia
•	Tumblr
•	Slack

LAMP is certainly an older web technology and often unloved for this reason. It’s an old design in the modern era, and often loses out on some of the advantages that we’ve gained since. But just because it doesn’t have those modern upsides doesn’t mean it’s all downside. Modern developers often don’t have a great opinion of LAMP stacks, even though the servers that rely on it are just about everywhere!


**WordPress LAMP Stack on AWS**

OK let's have some fun and setup a WordPress LAMP Stack on AWS!

We will create a fault tolerant WordPress site with high availability. A WP Admin will manage the site and content directly accessing on an EC2 instance that will upload both code and media to S3. Users will access the website through a load balancer to a group of EC2 instances that will download the code and media from S3. CloudFront will host and cache media files for performance.

This could be a typical small proof of concept example for a customer. We can use this as a real-life case study to create a fault tolerant WordPress site. We'll skip through the steps in AWS and will not document every small configuration detail. Please note this is a temporary environment and security considerations may be open. Production would use HTTPS 443 instead of HTTP port 80 and other restrictions.

Manually setting up a system yourself is a great way to help you understand how each cloud components are connected. In future blogs I hope to show you other methods to create a LAMP stack including using AWS Elastic Beanstalk and Serverless!

**Components Used**

- IAM Roles
- Security Groups
- VPC
- EC2
- S3
- Elastic Load Balancer
- Availability Zones
- Auto Scaling Groups
- Amazon RDS Multi-AZ MySQL
- CloudFront
- Route 53
- Linux
- Apache
- PHP
- WordPress

How easy is setup?

**Architecture Diagram**

 
![100.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645118115672/iDXFnV0Ra.jpeg)

**Login to AWS Console**
 

![Console.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122496392/Fv-BuiLal.jpeg)

**Networking & Content Delivery > VPC > Security Groups**

Create two new security groups in my default VPC

WebDMZ - port 22, 80 - source: 0.0.0.0/0

RDS-MYSQL/Aurora - port 3306 - source: Security group name for WebDMZ


**Database > RDS > Create database**


![2.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122537949/IS6MFUm4Q.jpeg)
 
MySQL – version 5.7.22
Production Template which will allow Multi-AZ DB instance


![51.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122579614/ZXwGsOQn5.jpeg)
 
Enter a DB instance identifier name with Master name and password

For test and billing purposes we will use a T2 Micro 20GB General Purpose SSD

Create DB instance that is not publicly accessible and in Default VPC choosing existing VPC security groups - RDS-MYSQL/Aurora


**S3 > Create bucket**

Create two S3 buckets

markbradley-wp-code / Bucket and objects not public

markbradley-wp-media / Public Access


**CloudFront > Distribution > Create distribution**

Create a distribution and use the S3 media bucket for the Origin Name and S3 FQDN for Origin Domain
 
![8.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645194524063/EGKtywahP.jpeg)

**Security, Identity, & Compliance > IAM > Roles > Create role**

AWS service - EC2

Permissions policies > AmazonS3FullAccess

Role name: S3forWP


**EC2**

Launch instance > Amazon Linux 2 AMI

![101.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122765263/SKwFkfh17.jpeg)

T2 micro - all default except IAM role: S3ForWP - Advanced Details - User data - bootstrap script
 

![12.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122799933/7zvEo8w4U.jpeg)

Bootstrap script 

Update

Install Apache, PHP, PHP-MySQL packages

Copy a healthy.html file in the /var/www/html folder

Download/install WordPress


Add Tag: Name / WPWriteNode

Select WebDMZ for Security Group (port 22, 80)


**Login to EC2 using Public IPv4 address with Key pair**

![21.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122837525/l2COyBBRc.jpeg)
 
Elevate privileges to <root> sudo su

Check WordPress files present

Check Apache service is started


**WordPress Configuration**

**Database > RDS > Databases** - Select database and copy Endpoint info

Open browser and EC2 IP address for WordPress GUI

Enter *endpoint* for Database Host and Database name, username, and password


![13.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122892752/_cMm3sJHc.jpeg)

Sorry, but I can’t write the wp-config.php file <error screen > Copy/paste text
 
![14.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645122928812/fQPjHBUVu.jpeg)

nano wp-config.php <edit> Copy/Paste - Ctrl-X - Y

Go back to GUI and click “Run the Installation”

Complete the welcome screen to install WP

![15.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645135967186/GtYguRifT.jpeg)
 
**Login to WP**
 
![24.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645123014388/qGTgou0WU.jpeg)

**See the WP Dashboard**

![17.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645123109371/NEjFDyt4G.jpeg)

Add post

Add photos to Media

Check website post

Right click copy image address

Paste in browser and confirm EC2 Public IP address

![27.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645123163613/Z0Si8Xo1y.jpeg)

Media files should be located on EC2 in wp-content folder
 
![28.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645123192769/S7bBYkJxb.jpeg)

**CMD line copy files to S3**

aws s3 cp /var/www/html/wp-content/uploads/2022/02 s3://markbradley-wp-media –recursive

aws s3 cp /var/www/html s3://markbradley-wp-code –recursive

After copy verify files

aws s3 ls s3://markbradley-wp-code


**URL rewrite rule for CloudFront**

**Networking & Content Delivery > CloudFront** -  Distributed domain name

![38.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645195272874/oNHFtC7-i.jpeg)

cd /var/www/html

nano .htaccess


![39.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136205970/gg9GA845u.jpeg)
 
Edit current CloudFront URL to include CloudFront Distributed domain name

Copy/Paste

Ctrl+X – Y

aws s3 sync /var/www/html s3://markbradley-wp-code

This will upload and change the edited .htaccess file in S3

This file will now point to CloudFront

**Configure Apache for URL rewrites**

cd /etc/httpd

ls

cd conf

ls

![34.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136318301/wFREgWLz1.jpeg)
 
nano httpd.conf

![35.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136332979/_ouQJGZBq.jpeg)
 
Find

![36.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136367852/ZjzV-6kmX.jpeg)
 
Edit AllowOverride ALL

![37.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136400124/0C15NyeCE.jpeg)

Ctrl+X - Y

service httpd restart


**Validate CloudFront is now hosting media files**

Open WP in browser and check post and images 

Right click copy image address

Paste in browser and confirm CloudFront address and not EC2 instance
 

![50.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136500616/0s4up4Ply.jpeg)

**Create Application Load balancer**

**Compute > EC2 > Load balancers** – Create load balancer
  

![18.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645136556752/FPuurf3eX.jpeg)

Application Load Balancer – HTTP HTTPS

Internet Facing - IPv4 – HTTP - All Availability Zones

Select Existing Security Group - WebDMZ

New Target Group - MyWPInstances

Target Type: Instance - Protocol: HTTP - Port: 80

Health Check - Protocol: HTTP - Path: /healthy.html
 
![40.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645195639287/zveIbfwQY.jpeg)


**Configure ReadNode EC2 for AMI to download S3 content and use for Auto Scale Group**

**Configure WriteNode EC2 to upload S3 content**


**Setup a cron job**

The cron command-line utility is a job scheduler that can run tasks at fixed times, dates, or intervals

**Login EC2**

cd /etc

nano crontab

![42.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645137165323/Gz7xkqcv5.jpeg)

<Edit>
*/1 * * * * root aws s3 sync --delete s3://markbradley-wp-code /var/www/html

![44.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645137236859/nISFJDP3Y.jpeg)
 
Ctrl+X > Y  > service crond restart

This task will download the S3 folder contents for the read node instance – Copy from S3 to local folder


**Test update to S3**

Add file hello.txt to s3://markbradley-wp-code

**Check EC2**

cd /var/www/html

hello.txt

cat hello.txt > displays text content


**Create Template for WPReadNode EC2**

**Compute > EC2** - Select instance > Action > Image > Create Image

Image Name: WPReadNode

Image Description: This is the default read node for WP

**Images > AMIs** - check image is available

![45.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645137399040/jTYg6Lns7.jpeg)

**Login to WP WriteNode EC2**

sudo su

cd /var/www/html/etc

clear

nano crontab

*/1 * * * * root aws s3 sync --delete /var/www/html s3://markbradley-wp-code

*/1 * * * * root aws s3 sync --delete /var/www/html/wp-content/uploads s3://markbradley-wp-media

Ctrl+X > Y

This task will upload the local folder contents to S3 for the write node instance.

**Test update to S3**

cd /var/www/html

echo "This is a TEST" > test.txt

service crond restart

service httpd status

**Check S3**

Check s3://markbradley-wp-code has test.txt file


**Setup Auto Scaling Groups using new AMI (read nodes)**

**Compute > EC2 > Auto Scaling Groups**

**Create Launch Template** – LCforWP - My AMIs – WPReadNode – T2.Micro – IAM role: S3ForWP Security Group: WebDMZ

 
![46.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645144132337/1-VqrJu0P.jpeg)

**Compute > EC2 > Target Groups** – Create target group

MyWPInstances – Target type: instance – HTTP – 80 – Default VPC – HTTP - /healthy.html

Actions – Register and deregister instance / IP targets

Check registered targets – healthy

![48.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645144247149/rtDB3Dq_O.jpeg)

**Create Auto Scaling Group** – ASGforWP – 3 instances – default VPC – all subnets

Check - Receive traffic from one or more load balancers

Target Group: MyWPInstances Health Check Type: ELB

![47.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645144280258/Em0ywWijQ.jpeg)


**Post implementation validation checks**

**EC2 Dashboard**

Check instances running

**Target Groups**

Check *all* registered targets - WPReadNode – healthy

**WP website**

Validate and open HTTP page with domain to view WordPress site hosted via Load Balancer

Open image file to see page and validate CloudFront address.

Edit Write Node EC2 and content is auto copied to S3 and S3 downloaded to Read Nodes EC2

Website is updated with new content

Check autoscaling by terminating running RN instances and verify new replacement instances

Auto Scaling Group – Activity History will confirm terminated instances and new EC2 instances

Check RDS by rebooting instance - primary will failover to secondary


**OPTIONAL Add Domain Name to WP site**

**Networking & Content Delivery > Route 53 > Hosted zones > Create hosted zone**

Create a hosted zone for your domain name

After creating Load balancer – Route 53 Alias

Hosted zones – Domain name

Create Record Set

A

Alias - Y

Alias Target: name of load balancer

Routing Policy: Simple

Evaluate Target Health - No


![22.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1645144383647/x26XBfCL0.jpeg)


**References**

[1] WordPress versions
https://codex.wordpress.org/WordPress_Versions

[2]WordPress and PHP Version Compatibility
https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/
