From © LinuxCapable
LEMP is a collection of open-source software commonly used to serve web applications. The term LEMP is an acronym that represents the configuration of a Linux operating system with an Nginx (pronounced engine-x, hence the E in the acronym) web server, with site data stored in a MySQL or MariaDB database and dynamic content processed by PHP that is popularly used for hosting extensive websites due to its performance and scalability.
In the following tutorial, you will learn how to install LEMP (Nginx, MariaDB, PHP) on Debian 11 Bullseye.
Prerequisites
- Recommended OS: Debian 11 Bullseye.
- User account: A user account with sudo or root access.
Update Operating System
Update your Debian operating system to make sure all existing packages are up to date:
sudo apt update && sudo apt upgrade -y
The tutorial will be using the sudo command and assuming you have sudo status.
To verify sudo status on your account:
sudo whoami
Example output showing sudo status:
[joshua@debian~]$ sudo whoami
root
To set up an existing or new sudo account, visit our tutorial on Adding a User to Sudoers on Debian.
To use the root account, use the following command with the root password to log in.
su
Install Depedencies
The first step is to install the dependencies needed during the installation, use the following command to install or check that they are present.
sudo apt-get install software-properties-common dirmngr ca-certificates apt-transport-https nano wget curl -y
Install Latest Nginx – (LEMP Stack)
To kickstart the LEMP stack installation, you will need to install the Nginx web server. A method is to install the latest Nginx mainline or stable from the Ondřej Surý repository to have the most updated software. Many Ubuntu users would know his PPA, and you can do the same in Debian.
To use the latest version of either Nginx mainline or stable, you will need first to import the repository.
Option 1. Import Mainline Repository:
curl -sSL https://packages.sury.org/nginx-mainline/README.txt | sudo bash -x
Option 2. Import Stable Repository:
curl -sSL https://packages.sury.org/nginx/README.txt | sudo bash -x
Update your repository to reflect the new change:
sudo apt update
Now that you have installed the Nginx repository and updated the repository list, install Nginx with the following:
sudo apt install nginx-core nginx-common nginx nginx-full
Example output:
Type Y, then press the ENTER KEY to proceed and complete the installation.
Note that you may be prompted to keep or replace your existing /etc/nginx/nginx.conf configuration file during the installation. It is recommended to keep your current configuration file by pressing (n). A copy will be made regardless of the maintainer’s version, and you can also check this in the future.
Now check to ensure the latest Nginx from the Ondřej Surý repository was installed using the apt-cache policy command. Note, the tutorial example installed Nginx Mainline:
apt-cache policy nginx
Example output for Nginx Mainline:
Install Brotli Support
You will notice additional modules will be available in this version, most notably brotli support. To enable brotli, follow the below steps.
Open your nginx.conf configuration file:
nano /etc/nginx/nginx.conf
Now add the additional lines before in the HTTP{} section:
brotli on;
brotli_comp_level 6;
brotli_static on;
brotli_types application/atom+xml application/javascript application/json application/rss+xml
application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
The brotli_comp_level can be set between 1 (lowest) and 11 (highest). Typically, most servers sit in the middle, but if your server is a monster, set to 11 and monitor CPU usage levels.
Next, test to make sure the changes are working correctly before making it live:
sudo nginx -t
If the changes are working correctly, you should see the following:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Now make the changes live by restarting your server:
sudo systemctl restart nginx
Next, enable Nginx on system boot:
sudo systemctl enable nginx
Lastly, verify Nginx is running correctly; this should be fine to skip if you ran the nginx -t command and got no errors.
systemctl status nginx
Example output:
Install Latest MariaDB Server
Import MariaDB 10.6/10.7 Repo using Official Bash Script
The official bash script is often the best and easiest way to install MariaDB on Debian 11, as you will receive instant updates if any security or new features comes available. This same method can be used to install the alternative versions such as MariaDB 10.5 and can be used to install MariaDB 10.8 and higher into the future, modify the mariadb-server-version={version number}.
In your terminal, use the following command.
Option 1. Import MariaDB 10.6 repository:
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version=10.6 --skip-maxscale --skip-tools
Option 2. Import MariaDB 10.7 repository:
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version=10.7 --skip-maxscale --skip-tools
If the command fails, you most likely forgot to install the curl package.
sudo apt install curl -y
Example output (MariaDB 10.7):
Note, the maxscale and tools were skipped. You can remove these flags, but at the current moment, tools are not supported for Debian 11 Bullseye at the time of this tutorial, but this will change. Most users will not need these extras.
This shows the repository has been successfully imported. Next, refresh your APT repository listing.
sudo apt update
Install MariaDB on Debian Desktop or Server
To install MariaDB, you will need to install the client and the server packages. This can be done as follows:
sudo apt install mariadb-server mariadb-client
Example output (MariaDB 10.7):
Type Y and then press the ENTER KEY to proceed with the installation.
Confirm the installation of MariaDB by checking the version and build:
mariadb --version
Example output:
mariadb Ver 15.1 Distrib 10.7.1-MariaDB, for debian-linux-gnu (x86_64) using readline EditLine wrapper
Remember, this is just an example. You can easily change the MariaDB as described at the start of the section.
Check MariaDB 10.7 Service Status
Now you have installed MariaDB, and you can verify the status of the database software by using the following systemctl command:
systemctl status mariadb
Example:
By default, you will find MariaDB status to be activated. If not, start MariaDB, use the following command:
sudo systemctl start mariadb
To stop MariaDB:
sudo systemctl stop mariadb
To enable MariaDB on system startup:
sudo systemctl enable mariadb
To disable MariaDB on system startup:
sudo systemctl disable mariadb
To restart the MariaDB service:
sudo systemctl restart mariadb
Secure MariaDB with Security Script
When installing MariaDB fresh, default settings are considered weak by most standards and cause concern for potentially allowing intrusion or exploiting hackers. A solution is to run the installation security script with the MariaDB installation.
First, use the following command to launch the (mysql_secure_installation):
sudo mysql_secure_installation
Next, follow below:
- Setting the password for root accounts.
- Removing root accounts that are accessible from outside the local host.
- Removing anonymous-user accounts.
- Removing the test database, which by default can be accessed by anonymous users.
Note, you use (Y) to remove everything.
Example:
[joshua@debian ~]$ sudo mariadb-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
haven't set the root password yet, you should just press enter here.
Enter current password for root (enter for none):
OK, successfully used password, moving on...
Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.
You already have your root account protected, so you can safely answer 'n'.
Switch to unix_socket authentication [Y/n] Y <---- Type Y then press the ENTER KEY.
Enabled successfully!
Reloading privilege tables..
... Success!
You already have your root account protected, so you can safely answer 'n'.
Change the root password? [Y/n] Y <---- Type Y then press the ENTER KEY.
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 <---- Type Y then press the ENTER KEY.
... 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 <---- Type Y then press the ENTER KEY.
... 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 <---- Type Y then press the ENTER KEY.
- 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 <---- Type Y then press the ENTER KEY.
... 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!
Install Latest PHP (PHP-FPM)
The last part of the tutorial will be to install PHP, which is the backend that communicates between Nginx and MariaDB, the middle man. PHP 8.0 is becoming relatively stable, and the newer versions of PHP 8.1 are now available.
By default, PHP is available in Debian’s default repository. However, to have the latest version similar to Nginx, the tutorial will focus on importing Ondřej Surý’s latest PHP version. This is always up to date even when new PHP versions are dropped.
Import Ondřej Surý PHP Repository
The first step is to import and install the GPG key before adding the repository.
In your terminal, use the following command.
In your terminal, use the following command to begin the installation.
curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x
This command will install the PHP repository and update your APT repository.
After running the update command, you may notice some packages require updating, make sure to do this before continuing.
sudo apt upgrade
Install Choice PHP 7.4 / 8.0 / 8.1 FPM
Nginx does not contain native PHP processing like other web servers like Apache. To handle the PHP files, you will need to install PHP-FPM “fastCGI process manager.”
First, check for updates on your system and install PHP-FPM, natively installing the PHP packages required.
To install PHP-FPM 7.4:
sudo apt install php7.4 php7.4-fpm php7.4-cli php7.4-curl php7.4-zip php7.4-mysql -y
To install PHP-FPM 8.0:
sudo apt install php8.0 php8.0-fpm php8.0-cli php8.0-curl php8.0-zip php8.0-mysql -y
To install PHP-FPM 8.1:
sudo apt install php8.1 php8.1-fpm php8.1-cli php8.1-curl php8.1-zip php8.1-mysql -y
Once installed, the PHP-FPM service is automatically started, and you can check the status to make sure it’s running ok.
Example with (PHP-FPM 8.1):
systemctl status php8.1-fpm
Example output:
As a reminder to see what version of PHP-FPM is installed on your system, use the following command.
php --version
Example output:
Create PHP Test Info Page
To test PHP-FPM with the Nginx Web server, you must create a file in the webroot directory.
For the guide, you will name the file (info.php) as follows:
sudo nano /var/www/html/info.php
Paste the following the (info.php) file:
<?php
phpinfo();
?>
Save the file (CTRL+O), then exit (CTRL+X).
Now in your Internet Browser address bar, enter (server-ip-address/info.php). If you have installed Nginx on your local computer, use the default (127.0.0.1/info.php) or (localhost/info.php).
Example:
This information shows PHP scripts can run properly with the Nginx web server.
For security purposes, you should remove the file. To do this, use the following command:
sudo rm -f /var/www/html/info.php
If you would prefer to keep the file for future purposes, add the following to your Nginx server block file in the server {} section:
location ^~ /info.php {
allow <YOUR IP ADDRESS>;
deny all;
}
This will only allow the IP address specified from accessing the file. It is advised to hide as much system info from potential hackers and malicious actors.
Create an Nginx Server Block
An Nginx server block is the equivalent of a virtual host in Apache, which contains a configuration for your Nginx web server that responds to the public visitors. Below is a complete example of achieving this with PHP-FPM in mind.
Create Server Block Directories
The (.conf) files are normally located in (sites-available) and (sites-enabled). Users coming from different distributions would notice this would be already installed; however, for Rocky Linux, you will need to create them.
Create the two required (sites) directory with the following command:
sudo mkdir /etc/nginx/sites-available && sudo mkdir /etc/nginx/sites-enabled
Edit the Nginx Configuration File
After creating the needed directories, edit Nginx’s main configuration file (nginx.conf) as follows:
sudo nano /etc/nginx/nginx.conf
Then paste the next few lines in the (HTTP) section of the (nginx.conf) configuration file:
include /etc/nginx/sites-enabled/*.conf;
server_names_hash_bucket_size 64;
Save the configuration with (CLTR+O) and then (CTRL+X) to exit.
Note, (server_names_hash_bucket_size) increases the memory allocated to parsing domain names.
Create Server Block Configuration File
Now create a server block file using any text editor, the guide will use (nano):
sudo nano /etc/nginx/sites-available/example.com.conf
Next, you need to set up the configuration file with a working example with PHP-FPM enabled.
An example is provided below for you to copy and paste. Note to replace (server_name) with your domain name or IP:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/html/example.com/;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php;
}
### DO NOT FORGET TO CHANGE php8.1-fpm.sock TO 8.0 OR 7.4 FOR ALTERNATIVE VERSIONS ###
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# A long browser cache lifetime can speed up repeat visits to your page
location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
access_log off;
log_not_found off;
expires 360d;
}
# disable access to hidden files
location ~ /\.ht {
access_log off;
log_not_found off;
deny all;
}
}
Now save the server block with (CTRL+O), then exit with (CTRL+X).
Create Test Landing Page
A good idea is to create a sample test site. Below is a standard test index.html set up:
If you haven’t already created your permanent or test web directory:
sudo mkdir -p /var/www/html/example.com/
You will need to configure the permissions, and you can set as the user currently logged in with the $USER variable:
sudo chown -R $USER:$USER /var/www/html/example.com/
The last permission setting is to allow the public to read the web directory (access your site) using permission chmod 755:
sudo chmod -R 755 /var/www
Next, create the index.html file:
sudo nano /var/www/html/example.com/index.html
Paste the content below. As you can see, it’s pretty basic as we are only using it for testing purposes.
<html>
<head>
<title>You have reached Example.com!</title>
</head>
<body>
<h1>Congratulations! The server block is active! Linuxcapable.com</h1>
</body>
</html>
Save the configuration with (CLTR+O) and then (CTRL+X) to exit.
Enable Nginx Server Block
You are now in the final stages, and now it is time to enable the server block configuration file. To do so, you need to create a symbolic link (symlink) for the server block configuration file in the (sites-available) directory to the (sites-enabled) directory using the following command:
sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
Test Nginx Server Block
To finish up, you should always do a dry run before restarting or reloading your Nginx service, which is critical if working in a live environment. Type the following command to test your server block configuration file:
sudo nginx -t
If there are no errors, you will get the following.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Next, open your Internet Browser and enter your domain address (example.com) to test if your server is reachable.
Congratulations, you have successfully created an Nginx server block that is PHP-FPM ready.
Secure Nginx with Let’s Encrypt SSL Free Certificate
Ideally, you would want to run your Nginx on HTTPS using an SSL certificate. The best way to do this is to use Let’s Encrypt, a free, automated, and open certificate authority run by the nonprofit Internet Security Research Group (ISRG).
First, install the certbot package as follows:
sudo apt install python3-certbot-nginx -y
Once installed, run the following command to start the creation of your certificate:
sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email you@example.com -d www.example.com
This ideal setup includes force HTTPS 301 redirects, a Strict-Transport-Security header, and OCSP Stapling. Just make sure to adjust the e-mail and domain name to your requirements.
Now your URL will be HTTPS://www.example.com instead of HTTP://www.example.com.
If you use the old HTTP URL, it will automatically redirect to HTTPS.
Comments and Conclusion
In the tutorial, you have learned how to install the LEMP stack to secure MariaDB, test PHP, and create an Nginx server block. Overall, LEMP is a smart option. Now, Nginx has surpassed Apache as the most used HTTP webserver software adequately configured and performance managed can give your webserver a decisive advantage over other setups.