How to install LEMP stack on Ubuntu 20.04

How to Install LEMP on Ubuntu 20.04

The Ubuntu operating system takes care of the first requirement. In this article, we will learn you How to install LEMP stack on Ubuntu 20.04, to get the rest of the components up and running.

The LEMP software stack(Linux, Nginx, MySQL, PHP) is a group of software that can be used to serve dynamic web pages and web applications written in PHP which describes a Linux operating system with an Nginx web server. The backend data is stored in the MySQL database and the dynamic processing is handled by PHP.




The tutorial may be more useful if you know:

Recommended Article: How to check Linux kernel version on VPS

How to install LEMP stack on Ubuntu 20.04

Let’s walk through the following steps to finish the tutorial and learn how to install Linux, Nginx, MySQL, PHP on Ubuntu 20.04.


Also, you can find related articles in:

how to install LEMP on CentOS 8

lamp-stack tutorial 

How to install LEMP on CentOS 8


1- Installing the Nginx Web Server

You need to employ Nginx, a high-performance web server, to display web pages to your site visitors. To do this use the apt package manager to obtain this software. But please consider that you must update it as this is the first time of using apt.

Run the following commands to update and to get Nginx installed:

sudo apt update  sudo apt install nginx

The Nginx web server will be active and running on your Ubuntu 20.04 server when you enter Y to confirm that you want to install Nginx when you are asked.

As we recommended you to enable the ufw firewall when you do this, you will need to allow connections to Nginx Luckily, Nginx registers a few profiles with ufw upon installation.

To check which UFW profiles are available:

sudo ufw app list
Available applications:    Nginx Full    Nginx HTTP    Nginx HTTPS    OpenSSH

You are recommended to enable the most restrictive profile that will still allow the traffic you need. Also, you will only need to allow regular HTTP traffic on port 80, as you may have not configured SSL for your server in this guide.

Use the command below to enable

sudo ufw allow 'Nginx HTTP'  

To verify the change:

sudo ufw status

If the HTTP traffic is now allowed, you will see this output:

Status: active    To                         Action      From  --                         ------      ----  OpenSSH                    ALLOW       Anywhere  Nginx HTTP                 ALLOW       Anywhere  OpenSSH (v6)               ALLOW       Anywhere (v6)  Nginx HTTP (v6)            ALLOW       Anywhere (v6)

You would add the new firewall rule, to be able to test if the server is up and running by accessing your server’s domain name or public IP address in your web browser. And run the command below to find it, if you do not have a domain name pointed at your server and you do not know your server’s public IP address.

Note: You can try each of them in turn in your web browser, after printing out a few IP addresses:

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

Aso, you can check which IP address is accessible, as viewed from other locations on the internet:

curl -4

To access Nginx’s default landing page, type the address you receive in your web browser.



welcome to nginx

When you see the page above, it means you have successfully installed Nginx and enabled HTTP traffic for your web server.


Buy VPS Server

2- Installing MySQL

Upon having a web server up and running, Let’s install the database system to be able to store and manage data for your site. As you know, MySQL is a popular database management system used in PHP environments.

Again, we use apt to acquire and install this software:

sudo apt install mysql-server  

By typing Y, and then ENTER, confirm the installation when you are asked.

You are recommended to run a security script that comes pre-installed with MySQL, once the installation is finished. You will do this to let the script to remove some insecure default settings and lock down access to your database system. Start the interactive script by running:

sudo mysql_secure_installation

Next, it will ask if you want to configure the VALIDATE PASSWORD PLUGIN. If you enable it, passwords that don’t match the specified criteria will be rejected by MySQL with an error. So, it is safe to leave validation disabled, but you should always use strong, unique passwords for database credentials.

At this point, answer Y for yes, or anything else to continue without enabling.

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:

After that, you’ll be asked to select a level of password validation, if you answer “yes”. Do not forget that if you enter 2 for the strongest level, you will receive errors when attempting to set any password which does not contain numbers, upper and lowercase letters, and special characters, or which is based on common dictionary words.

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

Whether you chose to set up the VALIDATE PASSWORD PLUGIN or not, your server will next ask you to select and confirm a password for the MySQL root user. This is not to be confused with the system root. The database root user is an administrative user with full privileges over the database system. you need to define a strong password here as an additional safety measure even though the default authentication method for the MySQL root user dispenses the use of a password, even when one is set.

Then, in case you enabled password validation, you’ll be shown the password strength for the root password you just entered and your server will ask if you want to continue with that password. Enter Y for “yes” at the prompt, if you are positive about your choice.

Estimated strength of the password: 100   Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y

To remove some anonymous users and the test database, disable remote root logins and load these new rules so that MySQL immediately respects the changes you have made, press Y and hit the ENTER key at each prompt for the rest of the questions.

To test if you’re able to log in to the MySQL console:

sudo mysql
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.    mysql>

To exit the MySQL console:

mysql > exit

On extra points, we could mention that you didn’t need to provide a password to connect as the root user, even though you have defined one when running the mysql_secure_installation scrip. The reason is that the default authentication method for the administrative MySQL user is unix_socket instead of password. Although this might look like a security concern at first, it makes the database server more secure because the only users allowed to log in as the root MySQL user are the system users with sudo privileges connecting from the console or through an application running with the same privileges. In fact, that means you won’t be able to use the administrative database root user to connect from your PHP application. Setting a password for the root MySQL account works as a safeguard, in case the default authentication method is changed from unix_socket to password.

It seems the best way of increasing security is to have dedicated user accounts with less expansive privileges set up for every database, especially if you plan on having multiple databases hosted on your server.


3- Installing PHP

Now, it is time to install PHP to process code and generate dynamic content for the web server.

For a better overall performance in most PHP-based websites, Apache embeds the PHP interpreter in each request and Nginx requires an external program to handle PHP processing and act as a bridge between the PHP interpreter itself and the web server but it requires additional configuration. However, it also requires additional configuration. Next, you should install php-fpm (PHP fastCGI process manager) and tell Nginx to pass PHP requests to this software for processing. Remember that the php-mysql, a PHP module that allows PHP to communicate with MySQL-based databases is required and Core PHP packages will automatically be installed as dependencies.

Use the following command to install the php-fpm and php-mysql packages.

sudo apt install php-fpm php-mysql  

As usual, type Y and ENTER to confirm the installation when you are asked.


4- Configuring Nginx to use the PHP processor

Similar to virtual hosts in Apache, you can create server blocks when using the Nginx web server to encapsulate configuration details and host more than one domain on a single server.

On Ubuntu 20.04, Nginx has one server block enabled by default and is configured to serve documents out of a directory at /var/www/html. It can become difficult to manage if you are hosting multiple sites until this works well for a single site.

Also, you can create a directory structure within /var/www for the your_domain website, leaving /var/www/html in place as the default directory to be served if a client request doesn’t match any other sites, instead of modifying /var/www/html.

To create the root web directory for your_domain:

sudo mkdir /var/www/your_domain  

Then, assign ownership of the directory with the $USER environment variable, which will reference your current system user:

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

Open a new configuration file in Nginx’s sites-available directory using your favorite command-line editor.

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

Paste in the following bare-bones configuration, when a new blank file is created.

server {      listen 80;      server_name your_domain www.your_domain;      root /var/www/your_domain;        index index.html index.htm index.php;        location / {          try_files $uri $uri/ =404;      }        location ~ \.php$ {          include snippets/fastcgi-php.conf;          fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;       }        location ~ /\.ht {          deny all;      }    }

To review what each of these directives and location blocks does, have a look at list below.

1- listen — Defines what port Nginx will listen to. In this case, it will listen on port 80, the default port for HTTP.

2root — Defines the document root where the files served by this website are stored.

3- index — Defines in which order Nginx will prioritize index files for this website. It is a common practice to list index.html files with higher precedence than index.php files to allow for quickly setting up a maintenance landing page in PHP applications. You can adjust these settings to better suit your application needs.

4- server_name — Defines which domain names and/or IP addresses this server block should respond to. Point this directive to your server’s domain name or public IP address.

5- location / — The first location block includes a try_files directive, which checks for the existence of files or directories matching a URI request. If Nginx cannot find the appropriate resource, it will return a 404 error.

6- location ~ \.php$ — This location block handles the actual PHP processing by pointing Nginx to the fastcgi-php.conf configuration file and the php7.4-fpm.sock file, which declares what socket is associated with php-fpm.

7- location ~ /\.ht — The last location block deals with .htaccess files, which Nginx does not process. By adding the deny all directive, if any .htaccess files happen to find their way into the document root, they will not be served to visitors.

If you’re using nano save and close the file by typing CTRL+X and then y and ENTER to confirm when you’re done editing.

Link to the config file from Nginx’s sites-enabled directory, to Active your configuration.

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/  

Therefore, Nginx would be told to use the configuration next time it is reloaded.

To test your configuration for syntax errors:

sudo nginx -t  

You can go back to your configuration file to review its contents before continuing, in case you faced any errors.

Then, reload Nginx to apply the changes:

sudo systemctl reload nginx  

Your new website is now active, but the webroot /var/www/your_domain is still empty. So to test your new server block works as expected, create an index.html file in that location.

nano /var/www/your_domain/index.html  
<html>    <head>      <title>your_domain website</title>    </head>    <body>      <h1>Hello World!</h1>        <p>This is the landing page of <strong>your_domain</strong>.</p>    </body>  </htm

To go to your browser and access your server’s domain name or IP address:


A page like below will appear:

Note: Viewing this page means your Nginx server block is working as expected.

landing test for LEMP

Now, you can leave this file in place as a temporary landing page for your application until you set up an index.php file to replace it. So, do not forget to remove or rename the index.html file from your document root, as it would take precedence over an index.php file by default.


5- Testing PHP with Nginx

Until this step, you did completely set up your LEMP stack. To validate that Nginx can correctly hand .php files off to your PHP processor, you can test it as we explain in the following.

To do this, create a test PHP file in your document root. Open a new file called info.php within your document root in your text editor:

nano /var/www/your_domain/info.php  

Next, paste the following lines into the new file. This is a valid PHP code that will return information about your server:

<?php  phpinfo();

Again, save and close the file by typing CTRL+X and then y and ENTER to confirm when you are finishing. And then you can access this page in your web browser by visiting the domain name or public IP address you’ve set up in your Nginx configuration file, followed by /info.php:


After that, you will see a web page containing detailed information about your server:




It is better to remove the file you created as it contains sensitive information about your PHP environment and your Ubuntu server when you checked the relevant information about your PHP server through that page. Use rm to remove that file.

sudo rm /var/www/your_domain/info.php

Note: You can always regenerate this file if you need it later.

Recommended Article: How to install LEMP stack on Ubuntu 20.04

6- Testing Database Connection from PHP (Optional)

Create a test table with dummy data and query for its contents from a PHP script, to test whether PHP is able to connect to MySQL and execute database queries. But first, you need to create a test database and a new MySQL user properly configured to access it.

Then, create a database named example_database and a user named example_user, which you can replace these names with different values.

Connect to the MySQL console using the root account:

sudo mysql

Use the command below to create a new database:

mysql > CREATE DATABASE example_database;  

After that, you can create a new user and grant them full privileges on the custom database you’ve just created.

By running the following command, you would create a new user named example_user, using mysql_native_password as the default authentication method. Remember to replace this value (password) with a secure password of your own choosing.

mysql > CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';  

Next, give this user permission over the example_database database:

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

This will give the example_user user full privileges over the example_database database while preventing this user from creating or modifying other databases on your server.

To exit the MySQL shell:

mysql > exit

By logging in to the MySQL console again, you can test if the new user has the proper permissions, this time using the custom user credentials:

mysql -u example_user -p  

In this command, attention to the -p flag, which will prompt you for the password used when creating the example_user user. after logging in to the MySQL console, confirm that you have access to the example_database database:

+--------------------+  | Database           |  +--------------------+  | example_database   |  | information_schema |  +--------------------+  2 rows in set (0.000 sec)

Now, create a test table named todo_list. From the MySQL console, run the following statement:

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

Insert a few rows of content in the test table and you can repeat the next command a few times, using different values:

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

Run the command below to confirm that you saved the data successfully to your table.

mysql > SELECT * FROM example_database.todo_list;  


+---------+--------------------------+  | 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)

You can exit the MySQL console, after confirming that you have valid data in your test table.

mysql > exit

The following PHP script connects to the MySQL database. And queries for the content of the todo_list table, exhibiting the results in a list. It will throw an exception If there’s a problem with the database connection. Copy this content into your todo_list.php script:


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/>”;

Now, you can save and close the file.

Finally, you will see a page like this, showing the content you’ve inserted in your test table:

viewing todo-list with LEMP stack on ubuntu

So, at this point, it means your PHP environment is ready to connect and interact with your MySQL server.


Dear user, we hope you would enjoy this tutorial How to install LEMP stack on Ubuntu 20.04, you can ask questions about this training in the comments section, or to solve other problems in the field of Eldernode training, refer to the Ask page section and raise your problems in it.


Also, read

Install WordPress with LEMP on Ubuntu 18.04

How to install lamp on Ubuntu 20.04

Install LAMP stack on CentOS 8

How to install LEMP stack on Debian 10

How useful was this post?

Click on a star to rate it!

Average rating 1 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

View More Posts
Marilyn Bisson
Content Writer
Eldernode Writer
We Are Waiting for your valuable comments and you can be sure that it will be answered in the shortest possible time.

Leave a Reply

Your email address will not be published. Required fields are marked *

We are by your side every step of the way

Think about developing your online business; We will protect it compassionately

We are by your side every step of the way


7 days a week, 24 hours a day