LEMP is an acronym that stands for the following software stack: Linux kernel, Nginx web server, MariaDB database (or MySQL), and the PHP server-side programming language. This software is widely used on servers on the Internet today to provide dynamic websites or interactive web applications.

Nginx is a modern and resource-efficient web server that is actively developed and is the second most used web server on the Internet after the Apache HTTP server. It is particularly fast because it uses an asynchronous, event-driven approach to processing requests.

This tutorial shows you how to install and configure the LEMP stack (Nginx with MariaDB and PHP 7) on the latest version of Debian 10.

REQUIREMENTS

  • The latest version of the Debian 10 operating system, which can be obtained from the following link https://www.debian.org/CD/http-ftp/, installed from scratch on a VPS, virtual machine or directly on a self-dedicated machine.
  • Direct access to the server’s console or a remote SSH connection.
  • A network interface configured with a static IP address for the machine
  • A registered public domain name with A and CNAME (www) DNS records configured on the name server side. In this guide, we use the example.com domain as an example.

Step 1: Initial Configuration

The first step is to log in with root or with a user with root privileges in your system and update Debian 10 components (kernel upgrades, package updates, and security patches) by issuing the following commands.

sudo apt  update
sudo apt upgrade
sudo apt dist-upgrade

Next, you make sure you add a descriptive name for your machine hostname by running the below command. Subsequently, you should restart the system in order to apply the new hostname accordingly.

sudo hostnamectl set-hostname hostname.yourdomain.com
sudo init 6

Next, go ahead and install net-tools wget, curl and bash-completion utilities in order to use them later to easily administer your Debian server.

sudo apt install net-tools sudo wget curl bash-completion

Step 2: Install the Nginx Web Server

Nginx is a modern and resources efficient web server used to display web pages to visitors on the internet. Install Nginx webserver from Debian 10 repository by running the below command in your server’s console.

sudo apt-get install nginx

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

As shown in the above image the apt package manager will check additional dependencies for the package and ask you if you agree to continue with the installation process. Answer with yes (y) in order to install Nginx.

Next, run netstat command in order to display network sockets on your system and verify if nginx daemon is listening on port 80/TCP. Alternatively, you might want to issue systemctl command in order to check the status of nginx daemon as illustrated in the below image.

sudo netstat -tlp
sudo netstat –tlpn
sudo systemctl status nginx.service

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Once the nginx server is up and running in your system, issue ifconfig command in order to display network interfaces information and list the IP addresses of your machine.  Then, open a browser and visit Nginx default web page via HTTP protocol by adding the IP address in your browser. The message “Wellcome to Nginx!” should be displayed in your browser window.

http://www.example.com

or

http://192.168.0.100

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Step 3: Activate Nginx HTTP/2.0 Protocol

By default, the latest versions of the Nginx binaries provided by the Debian 10 repositories are built with the HTTP/2.0 protocol. HTTP/2.0 is integrated with TSL/SSL protocols and can improve web page loading speed via secured transactions.

All modern browsers, such as Chrome or Firefox, should support this protocol by default. However, note that Microsoft Internet Explorer and Microsoft Edge browsers cannot yet parse the http2 protocol.

To enable the HTTP/2.0 protocol in Nginx on Debian 10, you need to make some changes to the default Nginx configuration file or create a new configuration file and add the TLS code block for 443 servers. To accomplish this, first create a backup of the default Nginx sites-available configuration by running the following command. Confirm that the backup was successful by listing the contents of the sites-available directory.

sudo cp /etc/nginx/sites-available/default{,.backup}
ls /etc/nginx/sites-available/

Next, create an Nginx TLS configuration file using a text editor and add the following content.

sudo nano /etc/nginx/sites-available/default-ssl

default-ssl file excerpt:

    server {
                listen 443 ssl http2 default_server;
                listen [::]:443 ssl http2 default_server;
                #server_name  www.domain.tld;
                server_name _;
                                
                root /var/www/html;
                                
                access_log /var/log/nginx/access.log;
                error_log /var/log/nginx/error.log;
                
                #SSL Certificates
                ssl_certificate "https://vitux.com/etc/nginx/ssl/cert.pem";
                ssl_certificate_key "https://vitux.com/etc/nginx/ssl/privekey.pem";
                ssl_dhparam /etc/nginx/ssl/dhparam.pem;
                
                ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
                #ssl_ciphers EECDH CHACHA20:EECDH AES128:RSA AES128:EECDH AES256:RSA AES256:EECDH 3DES:RSA 3DES:!MD5;
 
                ssl_session_cache shared:SSL:1m;
                ssl_session_timeout 10m;
                ssl_ciphers HIGH:!aNULL:!MD5;
                ssl_prefer_server_ciphers  on;
               
                add_header Strict-Transport-Security "max-age=31536000;
                #includeSubDomains" always;
 
                location / {
                index index.php index.html index.htm;
                    try_files $uri $uri/ /index.php?$args $uri/ =404;
                }
 
                                set $cache_uri $request_uri;
                
                location ~ /.well-known {
                allow all;
                               }
               location ~ .php$ {
                                include snippets/fastcgi-php.conf;
                #
                #             # With php-fpm (or other unix sockets):
                              fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                #             # With php-cgi (or other tcp sockets):
                #             fastcgi_pass 127.0.0.1:9000;
                }
 
                # deny access to .htaccess files, if Apache's document root
                # concurs with nginx's one
                #
                #location ~ /.ht {
                #             deny all;
                #}
                   }

The statement that enables the use of HTTP/2.0 protocol is represented by the word http2 from the below line.

 listen 443 ssl http2 default_server;

In case your visitor’s browsers don’t support HTTP2 protocol, remove the http2 word from your server configurations in order to disable the protocol and restart nginx service to apply changes.

In case you have a registered domain or you use virtual hosting based on IP addresses you should add your domain name or IP address after the server_name directive as shown in the below example.

server_name www.example.com example.com;

Once you finished editing Nginx default configuration file with the above settings

Configure SSL in Nginx

In the above TSL configuration file of nginx, we have specified the path for the TLS certificate and key. Since we have not yet installed the keys in your system, enter the following command to generate the self-signed SSL certificate file and key. During the generation of the SSL certificate, you will be asked a series of questions. Enter the two-digit code for your country, state, or province, the name of your city, the name of your organization, the name of your organization’s unit, the Common Name of your server, and a valid email address.  You should make sure to set the Common Name so that it matches the FQDN record of your computer from the DNS server or the IP address of your server used to access the website. The certificate and key are stored in a new directory under the nginx directory named ssl, as shown in the following screenshot.

sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/privekey.pem -out /etc/nginx/ssl/cert.pem
ls /etc/nginx/ssl/

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Also, generate a new strong Diffie-Hellman cipher, which can be found in the above configuration file on ssl_dhparam statement line, by issuing the below command:

sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Finally, after you’ve generated the Diffie-Hellman key, activate the TLS configuration file by creating a symbolic link for default-ssl configuration file from sites-available directory to sites-enabled directory by issuing the following command.

ln -s /etc/nginx/sites-available/default-ssl /etc/nginx/sites-enabled/

Next, test Nginx configuration file for syntax errors and, if everything is ok, restart Nginx daemon in order to apply all changes by running the below commands.

sudo nginx -t
sudo systemctl restart nginx.service

Check if SSL Configuration succeeded

In order to confirm if Nginx web server is binding on SSL port, issue netstat command and check if port 443 is displayed in listening mode.

netstat -tlpn | grep nginx

The below screenshot illustrated the above steps.

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Then, navigate to your domain name or your server’s IP address via HTTP protocol from a browser to display nginx default page. Because you’re using self-signed certificates, an error should be displayed in your browser. Confirm the error in order to pass to the nginx default main page.

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

In case Nginx doesn’t provide a default index.html page in webroot directory, issue the following command to create the index page.

echo "test page" | tee /var/www/html/index.html

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

In order to confirm the presence of HTTP/2.0 protocol advertised by Nginx, issue the below command. Look for h2 word in protocols advertised by the server.

 openssl s_client -connect localhost:443 -nextprotoneg ''

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

You can also visualize the state of the connection and check if the http2 protocol is advertised by Nginx from the Chrome browser by pressing F12 function key and request the page. In order to show the protocol used by the request, go to the Network tab, right-click on the Type menu and check Protocol filed. HTTP2 protocol should be displayed as h2 in the current protocol column, as illustrated in the below screenshot.

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Step 4: Install PHP 7

Nginx web server can serve dynamic web content with the help of PHP programming language interpreter via PHP FastCGI process manager to which Nginx passes the requests for processing. FastCGI process manager can be obtained by installing the php-fpm pre-compiled package offered by Debian 9 official repositories.

In order to install php-fpm process manager and PHP7.0 interpreter in the system alongside with the additional packages that will allow PHP to communicate with Nginx web server, issue the below command on your server console:

sudo apt install php7.3 php7.3-fpm php7.3-curl php7.3-gd

Start PHP-FPM

Once the PHP 7.3 interpreter has been successfully installed on your system, start and check php7.3-fpm daemon by issuing the below command:

sudo systemctl start php7.3-fpm
sudo systemctl status php7.3-fpm

In the above TLS configuration file of Nginx, we’ve already added the block configurations for PHP FastCGI process manager in order to serve dynamic content. The block of code that enables Nginx to use PHP interpreter is shown in the below excerpt, so no steps are needed further to modify Nginx TSL configuration file. The hashtag # sign from the beginning of the lines in the below screenshot are comments. Commented lines from configuration files are ignored by default by Nginx web server.

location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}

Test PHP Configuration

In order to test and validate if Nginx can correctly pass php files to PHP processor, create a PHP info.php test configuration file by issuing the below command

sudo su -c 'echo "" > /var/www/html/info.php'

Then, visit php info page in your web browser by navigating to your server’s domain name or public IP address followed by /info.php as shown in the below image.

https://www.example.com/info.php

or

http://192.168.0.100/info.php

You can also check if HTTP/2.0 protocol is advertised by the server by searching for the line $_SERVER[‘SERVER_PROTOCOL’] on PHP Variables.

To install other PHP7.3 modules, run the apt search php7.3 command to find a specific PHP module and install it. If you are planning to install a Content Management System, such as WordPress, then install these extra modules:

sudo apt install php7.3-mcrypt php7.3-mbstring

However, the newly installed PHP modules are not enabled by default on your system. In order to activate them, restart the PHP-FPM service.

sudo systemctl restart php7.3-fpm.service

Step 5: Install MariaDB Database

Finally, the last piece of the LAMP stack puzzle is missing in the database. The MariaDB database LEMP component is used to store records in tables and columns. It will dynamically manage the data of a web application. To install the MariaDB, run the following command in your server’s console. Then, restart the PHP FPM daemon to enable the PHP-MySQL module that is required to access the database.

sudo apt install mariadb-server mariadb-client php7.0-mysql
sudo systemctl restart php7.0-fpm.service

By default, the system root account or users with root privileges can access the database without providing a password. To change this behavior so that MySQL prompts for a password each time a system user tries to access the database, log in to the MySQL database using the command-line interface with root privileges and run the following commands in the MySQL console:

sudo mysql
MariaDB> use mysql;
MariaDB> update user set plugin='' where User='root';
MariaDB> flush privileges;
MariaDB> exit

Install Nginx with PHP and MySQL (LEMP) plus SSL on Debian 10 Debian

Set root password in MariaDB

In the next step, make sure you secure MariaDB by executing the security script mysql_secure_installation. It is provided by the installation package from Debian repositories. While running the script will ask a series of questions designed to secure MariaDB database. Such as: to change MySQL root password, removing anonymous users, disabling remote root logins, and delete the test database. Execute the script by issuing the below command. Say yes to all questions asked in order to fully secure MySQL daemon. Use the below script output except as a guide.

sudo mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
Enter current password for root (enter for none):

OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

You already have a root password set, so you can safely answer 'n'.

Change the root password? [Y/n] y

New password:

Re-enter new password:

Password updated successfully!

Reloading privilege tables..

 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y

 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] y

 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y

 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Finally, in order to test MariaDB functionality, log in to the database from the console and execute the following command. A list of the default databases should be displayed in the MariaDB console. Leave MariaDB console with exit statement.

mysql -u root –p
MariaDB [(none)]> show databases;
 -------------------- 
| Database           |
 -------------------- 
| information_schema |
| mysql              |
| performance_schema |
 -------------------- 
3 rows in set (0.00 sec)
 
MariaDB [(none)]> exit

That’s all! Nginx web server, MariaDB database, and PHP programming language are installed on your Debian 10 machine.  You can now start building dynamic websites or web applications for your visitors.