Port to the world of technology

Installing the LEMP stack (Linux, Nginx, MySQL, PHP) on Ubuntu 20.04


The LEMP software stack

These are a set of software, that is used to serve dynamic web pages and PHP web applications. LEMP is an acronym. The L and E stand for Linux operating system with an Nginx webserver. The E comes from the pronunciation of Nginx as Engine-X. M stands for MySQL database, which is the back-end data storage while P represents PHP. PHP handles dynamic processing.

In this article, we’ll look into the process of installing the LEMP stack on an Ubuntu 20.04 server.

Basic necessities to install LEMP on Ubuntu 20.04 server

To start this process you need to have access to an Ubuntu 20.04 server. You should be a regular, non-root sudo user, there should be a firewall enabled on your server. 

 Step 1- How to install an Nginx webserver

Nginx is a high-performance web server. So, it is used to display web pages to the site visitors.  We are going to use the apt package manager to get Nginx.

  • The first step in doing this is to update the server’s package index. Now use apt install to install Nginx.

$ sudo apt update

$ sudo apt install nginx

  • You have to enter Y in the prompt to confirm installing Nginx. Now, the Nginx web server will be running on your Ubuntu 20.04. 
  • Next, you have to allow connections to Nginx with your firewall as well. If you have the UFW firewalls you can check the registered UFW profiles with Nginx. Once installed Nginx register a few UFW application profiles. You can check them by running the following code.

$ sudo ufw app list

  • The list of available applications will be displayed as follows.

Available applications
Nginx Full
Nginx HTTP
Open SSH

  • The recommendation is to allow the most restricting profile. Thereby you can allow the traffic you need. In this guide, we’ll see how you can allow regular HTTP traffic on port 80.
  • Type the following code to enable this.

$ sudo ufw allow 'Nginx HTTP'

  • To verify the code, you can use the following code.

$ sudo ufw status 

  • You can see if the HTTP traffic is allowed in the output.


Status: Active

To               Action            From

__                _____            ____

OpenSSH           ALLOW            Anywhere

NginxHTTP         ALLOW            Anywhere

OpenSSH(v6)       ALLOW            Anywhere(v6)

NginxHTTP(v6)     ALLOW            Anywhere(v6)

  • Now go to the server’s domain name or public IP address in your web browser.

If you find it difficult to find those, type the following code to find out.

$ ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'

You have to try each of the IP addresses that will come up in your web browser.

  • Or else, you can check the IP address that is accessible as viewed from other locations on the internet by using the following code.

$ curl -4 icanhazip.com

Now type the IP addresses in your web browser. This will take you to the Nginx’s default landing page.


If you can see the following page, the first step is successful. You have now successfully installed Nginx and enabled HTTP traffic. 

Step 2- How to install MySQL

MySQL is a database management system. It can store and manage data. This is a popular database management system used in PHP sites.

  • Use the following code to acquire and install the software.

$ sudo apt install mysql-server

  • Next, confirm the command by pressing Y followed by Enter in the prompt.
  • Now run the security script. There is a preinstalled security script with MySQL. This is a method to remove insecure default settings by restricting access to the database.

You can use the following code to run the security script.

$ sudo mysql_secure_installation

  • Now, a prompt will appear to check whether you want to configure the VALIDATE PASSWORD PLUGIN.

When you enable this feature, MySQL will reject the passwords that don’t match the specified criteria. But do not enable validation. Instead, make sure that you always use strong and unique passwords for database credentials. 

If you want to enable this feature, confirm by pressing Y. In case, you do not want to enable you can press any other key you like. 

VALIDATE PASSWORD PLUGIN can be used to test passwords

and improve security. It checks the strength of password

and allows the users to set only those passwords which are

secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No:

  • If you like to enable password validation, the next step is to select a level of validation. There are three levels of password validation as Strong, Medium, and Low.  If you set for the strongest level only the passwords with numbers, special characters, upper and case letters. 

There are  three levels  of   password validation policy:

LOW     Length >= 8

MEDIUM  Length >= 8, numeric, mixed case, and special characters

STRONG  Length >= 8, numeric, mixed case, special characters and dictionary            file

Please enter  0 = LOW, 1 = MEDIUM and 2 = STRONG: 1

  • Next, you have to select a password for the MySQL root and confirm it. However, this is different from the system root.   

The database root user has authority over the database system. This is why you need a strong password if you wish to set one. Therefore, if you enabled password validation before, now you will be shown the strength of the password. You can choose if you want to continue with this password.  You can enter Y for Yes if you are satisfied with your password.

Estimated strength of the password:  100

Doyou wish to conntinue with the   password provided?(Press y|Y for Yes, any other key for No):y

  • Next, you have to press Y and ENTER on each question in the prompts.  These prompts remove anonymous users, test the database, disable remote root logins, and load new rules.
  • Now you can test if you can log in to MySQL

Simply type the following code.

$ sudo mysql

The word sudo is used to connect the MySQL server as the administrative database user root.

  • Now you will be able to see the output as the following code.


Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL  connection id is 22

Server  version : 8.0.19- 0ubuntu5 (Ubuntu)

Copyright (c) 2000,2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and /or its affiliates. Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


  • Finally, you can exit the   MySQL console by typing the following code.

mysql> exit

As the root user, you will not need a password to connect despite you entered password validation. This happens because the default authentication method is unix socket and not password. This is a more secure method because only the system users with sudo privileges that connect from the console or through any other application that run with the same privileges can log in to the database as root MySQL users. Therefore, you can’t use the administrative database root user to connect from the PHP application.  In case of the default authentication method is changed to password then having a password for the root MySQL account is an added advantage.

If you want to have multiple databases hosted on your server, it is best to create dedicated user accounts for every database.  They should have less expansive privileges to increase security.

However, if you are using MySQL8, the database users will need to configure mysql native password. This will be further elaborated in Step 6.

After installing MySQL, now we can see how you can install PHP.

Step 3 – How to install PHP

PHP helps to process code and create dynamic content for the webserver, while Nginx serves the content and MySQL store and manage data.

In Apache, the PHP interpreter is embedded in each request. But Nginx is different from that. There should be an external program that helps PHP processing. It also acts as a mediator between the PHP interpreter and the webserver. Even though it improves performance, it also requires additional configuration, especially with php-fpm and php-mysql.

PHP FastCGI process manager (php-fpm) helps to process the PHP requests. Therefore, after installing PHP FastCGI process manager, you should create a pathway between Nginx and this. You will also need php-mysql to communicate with the MySQL database. Other PHP packages are already installed.

Now let’s see how you can install php-fpm and php-mysql.

Simply type the following code.

$ sudo apt install php-fpm php-mysql

To confirm this action you have to type Y and ENTER.

Next, we’ll see how to use Nginx.

Step 4- How to configure Nginx in order to use PHP Processor

Similar to virtual hosts in Apache, you can create server blocks to capture configuration details on the Nginx web server. At the same time, you can host more than one server at a time. 

Now we’ll see how you can do this on Ubuntu 20.04. As an example, we will use your_domain as the domain name.

By default, Nginx has one server block enabled. This server block has a configuration to serve out of a directory at /var/www/html. Therefore, this works very well for a single site. But if you want to host multiple sites, this may not be the option.

Now we’ll see how you can create a directory structure within /var/www for your_domain website. In case a client request doesn’t match any other site, it is better to leave /var/www/html as the default directory.

  • First, type the given code to create the root web directory for your_domain website as follows.

$ sudo mkdir /var/www/your_domain

  • Now, use the following code to assign ownership of the directory with the $USER environment variable. This will reference your current system user.

$ sudo chown -R $USER:$USER /var/www/your_domain

  • Next, open a new configuration file in sites-available directory in Nginx. You can use a preferred command-line editor. We have used nano for the following code.

$ sudo nano /etc/nginx/sites-available/your_domain

  • Now you will get a new blank file. You have to paste the following bare-bones configuration. 

server {

      listen 80;

      server_name your_domain www.your_domain;

      root / var/www/you_domain;

      index index.html index.htm index.php;

      location / {

            try_flies $uri $uri/ =404;


      location ~ \.php$ {

          include snippets/fastcgi-php.conf;

          fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;


     location ~ /\.ht {

          deny all;



We’ll now see what each of these location blocks and directives mean.

  • listen -This is the port that Nginx listens on. As port 80 is the default port for HTTP, here we have selected that.
  • root – This is the root document. Root document stores the files served by the website. 
  • index – This defines the order of the index files that will be prioritized by Nginx. Usually, index.html files come before index.php.  You can set up the maintenance landing page in PHP applications quickly by using this. If you prefer otherwise, you can adjust the settings to your preference.
  • server_name – Mentions the domain names and/or IP addresses that the server block should respond to. You have to point the directive to the domain name of the server or public IP address.
  • Location- Try_file directive is included in the first location block. Try_files directive search for the files and directories that exist in regard to a URI request. A 404 error will appear in case Nginx can’t find the matched request.
  • Location~\.php$- This is the location block that handles the PHP processing. This is done by pointing the Nginx to the fastcgi-php.conf configuration file at the same time to the php7.4-fpm.sock file. Php7.4-fpm.sock file tells the file that is associated with php.fpm.
  • Location~/\.ht This location block is associated with the .htaccessfiles. Nginx can not process the .htaccessfiles.Therefore when the deny all directive is added .htaccessfiles in the document root will not be served to visitors.

Once you finish editing save the file and close it. You have to type CTRL+X Followed by y when you are using nano. Now press ENTER to confirm.

You can activate the configuration now. Simply link the config file from Nginx’s sites-enabled directory.

$ sudo In-s /etc/Nginx/sites-available/

The next time you reload Nginx , this code will direct to use the configuration. Type the following code to identify any syntax errors in the configuration. You have to review the contents of the configuration file to check any errors reported.

$ sudo nginx – t

You have to review the contents of the configuration file in the event of reported errors. When you have finished reviewing you can continue.

Next, you have to reload Nginx to apply the changes.

$ sudo systemctl reload nginx

Now your new website is active. Then create another file in the webroot as it is still empty. By typing the following code, you create a index.html file in the /var/www/your_domain location you can test the new server block.

$ nano /var/www/your_domain/index.html



      <title>your_domain website</title>



       <h1>Hello World!</h1>

       <p> This is the landing page of <strong>your_domain</string>.</p>



You can now see the following page when you access the domain name of the server or IP address in your web browser. You have to use the domain name or IP address that is listed within the server_name directive in the server block configuration file.

However, this is a temporary landing page. you have to set up an index.php file to replace it. You have to make sure to remove or rename the index.html file once you create the index.php file.

Now you have successfully configured the LEMP stack. Next, you have to test if Nginx is able to handle .php files on this new website. Let’s see how you can create the .php file to test this.

Step 5 – How to test PHP with Nginx 

To create a .php file to test if Nginx can hand over the document to the PHP processor follow the guide given below.

First, create a test php file in your document root. You have to go to your document root text editor and open a new file called info.php.

$ nano /var/www/your_domain/info.php

Type the following code to receive information about your server.




To save and close the file, type CTRL+X followed by y  Then you have to ENTER to confirm.

Now when you want to access the website simply type the domain name or the IP address followed by /info.php. For example,


You will be able to see a web page that displays detailed information about the server.

You have to check the relevant information regarding your page. Use rm to remove the file that contains sensitive information about your PHP environment and Ubuntu server. However, you will be able to regenerate it if you need it in the future.

Step 6- How to test the database connection from PHP (Optional step)

This step is optional, however, if you want you can test the abilities of PHP to connect to MySQL and execute database queries. First, you have to create a test table with some dummy data and query for the contents from a PHP script.

The default authentication method for My SQL 8 is caching_sha2_authentication. If you are using an older version, you will need to create a new user with the mysql_native_password authentication method. This will enable the connection between the MySQL database and PHP.

Let us see how you can create a database called example_database and a user named example_user. If you want you can replace the names with your choice.

To start this, you have to first connect to the MySQL console using the root account.

$ sudo mysql

Next, use the following code to create a new database from the MySQL console.

mysql> CREATE DATABASE example_database;

Now you can create a new user and set a password for authentication by using the following code. You can replace the example_user and password.

mysql> CREATE USER 'example user' @'%' IDENTIFIED WITH mysql_native_password BY 'password':

Now, use the following code to provide permission to the user over the example_database database. 

mysql> GRANT ALL ON example_database.* TO 'example_user'@'%';

This code prevents the example_user from creating or modifying other databases on your server at the same time giving full privileges over example_database

You can now, exit the MySQL shell using the following.

mysql> exit

If you want to check whether the new user has appropriate permission, login to the MySQL console using custom user credentials as given below.

$ mysql -u example_user -p

The -p flag in the above command indicates the prompt that was set up earlier in example_user to enter the password. Now login to MySQL console. Then you can confirm that you have access to the example_database database.


Then you will be able to see the following output.


| Database           |


| example_database   |

| information_schema |


2 rows in set (0.000 sec)

Next, you can create a test table named todo_list by running the following command in MySQL console.


  • mysql> CREATE TABLE example_database.todo_list (
  • mysql> item_id INT AUTO_INCREMENT,
  • mysql> content VARCHAR(255),
  • mysql> PRIMARY KEY(item_id)
  • mysql> );

Use the following command to insert rows of content to the test table. You have to repeat the command a few times with different values.

mysql>  INSERT INTO example_database.todo_list (content) VALUES ("My first important item");

Now the following output will be visible.



| item_id | content                  |


|     1 | My first important item    |

|    2 | My second important item    |

|    3 | My third important item     |

|   4 | and this one more thing      |


4 rows in set (0.000 sec)

Now confirm that you have valid data in your test table. If so exit the MySQL console by using the following command.

mysql > exit

After this, you have to create a PHP script to connect the query for your content to the MySQL. Choose the editor you prefer. Then create a new PHP file in your custom web root directory. This is how it would look like if you use nano.

$ nano /var/www/your_domain/todo_list.php

Now copy the following commands to the todo_list.php script. It connects the MySQL database and queries to the todo_list table. The results will be shown in a list.  There will be an exception in case there is a problem with the database connection.


<?php $user = "example_user"; $password = "password"; $database = "example_database"; $table = "todo_list";

try { $db = new PDO("mysql:host=localhost;dbname=$database", $user, $password); echo "<h2>TODO</h2><ol>"; foreach($db->query("SELECT content FROM $table") as $row) { echo "<li>" . $row['content'] . "</li>"; } echo "</ol>"; } catch (PDOException $e) { print "Error!: " . $e->getMessage() . "<br/>"; die(); }

Once you finish editing save the changes and close the file.

Access the web page by adding /todo_list.php after the domain name or the public IP address that is configured for your website. An example is given below.


Then you will be able to see a page as follows.

Now your PHP environment is ready to connect and interact with the MySQL server.

Leave A Reply