How to Install LEMP on Ubuntu 18.04

LEMP is a much similar stack of components as the classic LAMP, except the web server Apache replaced by Nginx pronounced Engine-x, explaining the 'E' on LEMP. Nginx is an open source reverse proxy server for HTTP, HTTPS, and for some others protocols which also functions as a load balancer, HTTP cache, and web server (origin server). You can link the MySql or MariaDB database but we will use MySql in this tutorial for the database.

This tutorial will show you the steps to install LEMP on your Ubuntu 18.04 server.

Step 1- Install and configure the web server Nginx

If you launch your Ubuntu 18.04 server for the first time, make sure to update the cache of the packages

# apt update

Now you can install Nginx

# apt install nginx
Reading state information... Done
The following additional packages will be installed:
 fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libnginx-mod-http-geoip libnginx-mod-http-image-filter
 libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6 libxpm4 nginx-common nginx-core

You can check the status of the web server

# systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2018-06-10 04:51:51 UTC; 2min 0s ago
     Docs: man:nginx(8)
...
...

Now make sure that nginx will start at the same time as the system if it reboots

# systemctl enable nginx.service
Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable nginx

Now if you have your UFW firewall running, you will need to allow connections to Nginx. Different applications can register their profiles with UFW upon installation such as Nginx so you can check it as below

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

You can enable it with the name and the protocol to use (http or https)

# ufw allow 'Nginx HTTP'
Rule added
Rule added (v6)

Now you can check the service allowed on your firewall as below

# ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
Postfix                    ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)             
Postfix (v6)               ALLOW       Anywhere (v6)

Now you can check your web server in your browser

Step 2- Install and configure the MySql database

Now you can install your database management MySql on your Ubuntu 18.04

# apt install mysql-server
Reading package lists... Done
Building dependency tree 
Reading state information... Done
The following additional packages will be installed:
 libaio1 libcgi-fast-perl libcgi-pm-perl libencode-locale-perl libevent-core-2.1-6 libfcgi-perl libhtml-parser-perl libhtml-tagset-perl
.....
.....

Then run the commands below to secure MySql server. it will ask if you want to configure the VALIDATE PASSWORD PLUGIN in order to set a secure mysql root password

# mysql_secure_installation

Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

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: y

It will show you three level of the password strength. Choose the one most appropriate for you but make sure to keep it in mind to avoid some access error.

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

Now you can enter the database root password

Please set the password for root here.

New password: 

Re-enter new password: 

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

You will be asked for some others security questions:

  • Remove anonymous users? (Press y|Y for Yes, any other key for No): Y
  • Disallow root login remotely? (Press y|Y for Yes, any other key for No): Y
  • Remove test database and access to it? (Press y|Y for Yes, any other key for No):  Y
  • Reload privilege tables now? (Press y|Y for Yes, any other key for No):  Y

Now you can connect to your database with the command

# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.22-0ubuntu18.04.1 (Ubuntu)

But you should notice that there are still some security breaches in our database because, in Ubuntu systems running MySQL 5.7 (and later versions), the root MySQL user is set to authenticate using the auth_socket plugin by default rather than with a password. It authenticates clients that connect from the local host through the Unix socket file. You can check your MySql version

# mysql --version
mysql Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using EditLine wrapper

Now you can check the authentication method each of your MySQL user accounts. First, connect to the database

# mysql

Notice that it didn't ask you for the database root password as we have configured above. It means that everybody accessing your server can edit your database. Now check the authentication method

mysql> SELECT user,authentication_string,plugin,host FROM mysql.user;
+------------------+-------------------------------------------+-----------------------+-----------+
| user             | authentication_string                     | plugin                | host      |
+------------------+-------------------------------------------+-----------------------+-----------+
| root             |                                           | auth_socket           | localhost |
| mysql.session    | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| debian-sys-maint | *4A9F410D01A83957975233C9B87881861B0CDF9C | mysql_native_password | localhost |
+------------------+-------------------------------------------+-----------------------+-----------+
4 rows in set (0.00 sec)

You can see that the authentication method of the root database user is not the password. You can change it as below

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your-db-root-password';
Query OK, 0 rows affected (0.00 sec)

Now flush the privileges

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Now you can check if the authentication method has changed

mysql> SELECT user,authentication_string,plugin,host FROM mysql.user;
+------------------+-------------------------------------------+-----------------------+-----------+
| user             | authentication_string                     | plugin                | host      |
+------------------+-------------------------------------------+-----------------------+-----------+
| root             | *BCF4F28E525ED7EE4664FFFF4DAE13EC14A6ABE1 | mysql_native_password | localhost |
| mysql.session    | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys        | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| debian-sys-maint | *4A9F410D01A83957975233C9B87881861B0CDF9C | mysql_native_password | localhost |
+------------------+-------------------------------------------+-----------------------+-----------+

Now you can exit

mysql> exit
Bye

Check again to log into your mysql database only with the mysql command

# mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

This message tells you what is wrong. It means that you probably have a password set for the user root from the database and need to enter it with the command

# mysql --password
Enter password:

or

# mysql -u root -p
Enter password:

In the second command, notice that the -u root indicates the database user (root) to use for the connection to the database. It means that if you have paul or john user, you can use it instead of root.

Now your database is most secured.

Step 3 -  Install PHP and configure PHP-FPM Settings

As Nginx does not contain native PHP processing, we have to install php-fpm (FastCGI Process Manager) and php-mysql to allow PHP to communicate with the MySQL database.

apt install php-fpm php-mysql
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libsodium23 php-common php7.2-cli php7.2-common php7.2-fpm php7.2-json php7.2-mysql php7.2-opcache php7.2-readline
Suggested packages:
  php-pear

You can check the version of your php

# php --version
PHP 7.2.5-0ubuntu0.18.04.1 (cli) (built: May 9 2018 17:21:02) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
 with Zend OPcache v7.2.5-0ubuntu0.18.04.1, Copyright (c) 1999-2018, by Zend Technologies

Now open the PHP-FPM default file to edit the following content

# vim /etc/php/7.2/fpm/php.ini
cgi.fix_pathinfo=0
date.timezone = Africa/Douala

save the file and restart php-fpm

# systemctl restart php7.2-fpm

Depending on what version of Nginx and PHP you install, you may need to manually configure the location of the PHP socket that Nginx will connect to. So List the contents for the directory /var/run/php/

# ls /var/run/php/
php7.2-fpm.pid php7.2-fpm.sock

We can see that the socket is php7.2-fpm.sock. Now we can open the Nginx site configuration file to use PHP for dynamic content and we should indicate the socket file.

# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or WordPress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;
        index index.php index.html index.htm index.nginx-debian.html;

        server_name www.linoserver.com;

        location / {
                try_files $uri $uri/ =404;
        }    

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.2-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

        # redirect server error pages to the static page /50x.html
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
                root /var/www/html;
        }
        location ~ /\.ht {
                deny all;
        }    
}

Now you can check the syntax of the Nginx configuration file and make to have the good PHP socket indicated in the file

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now you can create a php file to check the configuration

# vim /var/www/html/info.php
<?php
phpinfo();

Now you can check your configuration

Now you can delete the php test file.

Read also

Configuring Nginx takes some time, but it's worth it and it's also easy to configure it to host your web applications. Now you have all of the required components to configure LEMP on your Ubuntu 18.04 server.

Alain Francois 12:42 am

About Alain Francois

IT Linux administrator passionate of free and open source software, I work on Linux Systems since some years on installations and deployments of certain solutions. I like to share my experiences with a wider audience by training and conferences.

Author Archive Page

Have anything to say?

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

All comments are subject to moderation.

2 Comments

  1. "Now we can open the Nginx site configuration file to use PHP for dynamic content and we should indicate the socket file."

    It is worth mentioning this file is located at /etc/nginx/sites-available/default .