How to implement a LEMP Stack on a ubuntu server in AWS EC2
Tags: devops, aws, tutorial, linux
Published: 2022-07-06 15:52:00

In this post, I will demonstrate steps on how you can implement a LEMP stack on ubuntu server in AWS EC2 virtual machine.

**LEMP** is an acronym that stands for 
**Linux** - Operating System
Nginx (pronounced as **engine-x**, hence the E in the acronym). web server.
**MySql** - Database.
**Php** - Scripting Language.

LEMP is a variation of LAMP (Linux, Apache, MySql and Php) and a common stack used in web development and deployment.
In this post, I will show you how to deploy a simple php app(todo_list.php) to test a our configuration and deployment.

**Requirements:**
Basic Linux skills
Basic MySql skills
AWS Free Account [Here](https://aws.amazon.com/free/?trk=712ee378-d73b-4293-9bad-8ce09671ea7c&sc_channel=ps&sc_campaign=acquisition&sc_medium=ACQ-P|PS-GO|Brand|Desktop|SU|AWS|Core|EEM|EN|Text&s_kwcid=AL!4422!3!444219541835!e!!g!!aws%20free%20tier&ef_id=CjwKCAjw6MKXBhA5EiwANWLODILIqfuerJ_6Op_gqK93urjZNr90K0GY4dh7KAalnH2IFSLf5MekfBoCeNgQAvD_BwE:G:s&s_kwcid=AL!4422!3!444219541835!e!!g!!aws%20free%20tier&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all)

**STEP ONE**

Login into your AWS account, Lunch Ec2 instance with your prefered settings. 

1. SSH into the Linux terminal AWS EC2 to update the packages and install nginx webserver.

`sudo apt update`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zj65mceszj35iawk2pw.png)

`sudo apt install nginx`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67iy4ugl9cdg0haecjtz.png)

2. Verify ngnix is successfully running.

`sudo systemctl status nginx`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/il6mgk61txpdpbci6bki.png)

3. To access the nginx web server locally and in the browser - make sure the default (port 80) is opened in your security group settings.

- Locally
`curl http://localhost`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zhil1a0nztgtfipew5ws.png)

- In the browser (use the public Ip address of the vm)
`curl http://44.203.157.197/`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7w1msj5kou0q4p9b8xj4.png)

**STEP TWO**

Installation of the database - MySql.

1. Install MySql

`sudo apt install mysql-server`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s81731e0swjvjexsmz6s.png)

2. Login into MySql

`sudo mysql`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mejyeo0jcczjjhipfdsh.png)

3. Currently, we are login as the Admin (sudo mysql). Set a new password for the Admin/root by using mysql_native_password as default authentication method and the exit.

`ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'PassWord.1';`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n22hozelipvstzf7bv67.png)

4.  For security reasons, we need to remove all insecure default settings (e.g, password strength, test database e.t.c) by a pre-installed script.

`sudo mysql_secure_installation;`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhckcxpxid68nrzn3g08.png)

5. Test MySql Admin/root login and exit.

`sudo mysql -p`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62qm3yx20dtx0e8tm1sp.png)

**STEP THREE**

PHP installation

1. We would need to install two packages.
 - php fastCGI
protocol for interfacing interactive programs with a web serve and minimize the memory consumption and rise the performance for the web server with heavy traffic.

- Php-MySQL - php module that allows communication between php and mysql database.

`sudo apt install php-fpm php-mysql`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c1hmmajlq9qhzmo81nq.png)


**STEP FOUR**

Configuring Nginx to use the Php processor.

1. Create a web directory to host our application which is different from the default at /var/www/html. Additional, assign ownership of the current system user to the newly create directory.

`sudo mkdir /var/www/projectLEMP`

`sudo chown -R $USER:$USER /var/www/projectLEMP`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kadcka8t0aoe35qo0yqh.png)

2. Create a new configuration file for projectLEMP directory.

`sudo nano /etc/nginx/sites-available/projectLEMP`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iusv2003uo46j37vq1e9.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83hwndc05l28bodpf0lh.png)

3. Activate your configuration by linking to the config file from Nginx’s sites-enabled directory and test for error in the configuration file.

`sudo ln -s /etc/nginx/sites-available/projectLEMP /etc/nginx/sites-enabled/`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6sub1exy2ybfoq16e32.png)

4. Test configuration for error

`sudo nginx -t`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpu9lr6dgjc8colr41st.png)

4. Disable the default ngix host/directory *defualt* which listen on port 80 and reload ngnix.

`sudo unlink /etc/nginx/sites-enabled/default`

`sudo systemctl reload nginx`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jvm9mgf4omr8wdnob6o1.png)

5. Create an index.html to test the custom directory *proectLEMP*.

`sudo echo 'Hello LEMP from hostname' $(curl -s http://169.254.169.254/latest/meta-data/public-hostname) 'with public IP' $(curl -s http://169.254.169.254/latest/meta-data/public-ipv4) > /var/www/projectLEMP/index.html`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcavbazjz6chiuwcmewt.png)

- View in browser (using public ip address).


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99o4960neg0fzn7zcwgu.png)

- View in browser (using dns address).


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/alhi5s10wnfb2dd0v146.png)

**STEP FIVE**

Test to make sure Nginx can handle *.php* files.

1. Create a info.php.

`sudo nano /var/www/projectLEMp/info.php`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ah9hn380skorffpo6wzn.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7leq08zzc7g8plgymug9.png)

2. Test in the browser with the vm dns or ip.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0gqbqklhwto8rnr8r9i.png)

3. For security reasons, delete the info.php file. It can also be generated we needed.

`sudo rm /var/www/projectLEMp/info.php`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3185l689re4f4eip4z4k.png)


**STEP SIX**

Retrieving data from MySQL using Php.

1. Login into mysql (Admin/root account)
`sudo mysql -p`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5whl9t0x4h699am8mu3.png)

2. Create a database

`create database project2db `


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2e0gfoqbwhy6kylmsl9n.png)

3. Create user and password.

`CREATE USER 'project2_user'@'%' IDENTIFIED WITH mysql_native_password BY 'PassWord.2';`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rqjfsbbmsffemp5tzq75.png)

- Grant full privileges and exit.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdb6g2ulbegohrjx28kk.png)

4. Login with the new user credentials.

`mysql -u example_user -p`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k086rdlg6mjlw0ykx4in.png)

5. View the databases in the MySQL database sever.

`show databases;`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86uthze4x7w3n9bxmsli.png)

6. Create a table

`CREATE TABLE project2db.todo_list ( item_id INT AUTO_INCREMENT, content VARCHAR(255), PRIMARY KEY(item_id));`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tizsf8wwkhquflsfe7br.png)

7. Insert some records into the table.

`CREATE TABLE project2db.todo_list ( item_id INT AUTO_INCREMENT, content VARCHAR(255), PRIMARY KEY(item_id));`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sorbjlxp24hkywxz3xl0.png)

8. Confirm the data is saved into the table and exit.

`SELECT * FROM project2db.todo_list;`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0s4qatclz2po3axqaarz.png)

8. Create a php page to fetch the data from the database.

`nano /var/www/projectLEMP/todo_list.php`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bou0xg5d2d4vb032agy6.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zse8rxnll55bmwmgemcf.png)

save and close.

9. Use your public Ip to view the sample todo_list.php page in the browser.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxgxv2uejwadksk4mjwy.png)

**Congratulations!!!** You have successfully deploy a LEMP stack on AWS EC2. Similarly, you can deploy your LEMP application and additionally, configure the DNS with the public IP to you use your domain name.

I hope this helps someone.

Please feel free to share your tips, questions, corrections in the comments!

#Thank you for reading!