LEMP Stack

Introduction: Why LEMP Over LAMP?

 

For a low-resource or free VPS hosting environment, choosing the right software stack is critical. We recommend the LEMP stack (Linux, Nginx, MySQL/MariaDB, PHP-FPM) because its web server, Nginx (pronounced “Engine-X”), uses an event-driven architecture that is significantly more efficient at handling concurrent connections and consumes less memory compared to Apache (used in the LAMP stack).

This guide assumes you have completed the [50-Point VPS Hardening Checklist] (Internal Link) and are logged in as your non-root sudo user.

Phase 1: Installing Nginx (The Web Server)

 

Nginx will be the front-facing server that handles user requests, routing dynamic requests (like PHP) to the processor and serving static files directly.

Step 1.1: Install Nginx

 

Start by ensuring your system package list is up-to-date and installing Nginx:

Bash

sudo apt update
sudo apt install nginx -y

Step 1.2: Configure Firewall (UFW)

 

Because you have previously enabled UFW, you must now explicitly allow the web server traffic. Nginx registers profiles with UFW for easy management.

  1. Check available profiles:

    Bash

    sudo ufw app list
    
  2. Allow the Nginx Full profile (covers both HTTP on port 80 and HTTPS on port 443):

    Bash

    sudo ufw allow 'Nginx Full'
    
  3. Verify the new firewall status:

    Bash

    sudo ufw status
    

    You should see your new SSH port, Nginx Full (or 80/tcp and 443/tcp), and the OpenSSH rule listed as allowed.

Step 1.3: Test Nginx Installation

 

Verify Nginx is active and running, then check its default page.

  1. Check Nginx service status:

    Bash

    sudo systemctl status nginx
    

    The output should show Active: active (running).

  2. Access the server: Open your web browser and navigate to http://your_vps_ip_address. You should see the default “Welcome to nginx!” page.

Phase 2: Installing and Securing MariaDB (The Database)

 

MariaDB is a fast, community-developed fork of MySQL. We will install it and immediately run the critical security script.

Step 2.1: Install MariaDB Server

 

Bash

sudo apt install mariadb-server mariadb-client -y

Step 2.2: Run the Critical Security Script

 

The default MariaDB installation is insecure. This script addresses common vulnerabilities like remote root login and anonymous users. Do not skip this step.

Bash

sudo mysql_secure_installation

You will be prompted to make several crucial choices:

  • Set root password? Choose Y and create a strong, unique password. You will rarely use this, as application users are preferred.

  • Remove anonymous users? Choose Y.

  • Disallow root login remotely? Choose Y. This is essential, as it prevents external login to the database as the master root user.

  • Remove test database and access to it? Choose Y.

  • Reload privilege tables now? Choose Y.

Step 2.3: Create a Database and User

 

You should never use the database root user for your application (e.g., WordPress). Create a dedicated database and user with minimal privileges.

SQL

sudo mysql

Inside the MariaDB shell, run the following commands, replacing the bold text:

SQL

CREATE DATABASE your_app_db_name;
CREATE USER 'your_app_user'@'localhost' IDENTIFIED BY 'a_very_strong_password';
GRANT ALL PRIVILEGES ON your_app_db_name.* TO 'your_app_user'@'localhost' IDENTIFIED BY 'a_very_strong_password';
FLUSH PRIVILEGES;
EXIT;

Phase 3: Installing and Configuring PHP-FPM

 

Nginx cannot process PHP files natively. It requires PHP-FPM (FastCGI Process Manager) to handle PHP requests and pass the final HTML back to Nginx.

Step 3.1: Install PHP-FPM and Extensions

 

Install the core PHP-FPM package and the necessary extension to communicate with MariaDB/MySQL:

Bash

sudo apt install php-fpm php-mysql -y

Step 3.2: Configure PHP-FPM for Better Security

 

The PHP-FPM default configuration has a security setting that should be disabled for multi-site hosting. Since you’re running a single VPS, setting this is a good practice.

Open the configuration file (version may vary, check /etc/php/ for your version, e.g., 8.3):

Bash

sudo nano /etc/php/8.3/fpm/php.ini

Find the line ;cgi.fix_pathinfo=1 and change it to:

Ini, TOML

cgi.fix_pathinfo=0

Remove the semicolon (;) to uncomment it. This prevents Nginx from executing scripts with names that closely match a file. Save and close the file (Ctrl+X, Y, Enter).

Step 3.3: Restart PHP-FPM

 

Apply the new setting:

Bash

sudo systemctl restart php8.3-fpm

Phase 4: Nginx Server Block Configuration

 

This step tells Nginx where your website files are located and how to process the PHP files using the PHP-FPM socket.

Step 4.1: Create Web Root Directory

 

Create a directory for your domain, replacing yourdomain.net:

Bash

sudo mkdir -p /var/www/yourdomain.net/html

Set the ownership to your non-root user (using the $USER variable) so you can manage the files:

Bash

sudo chown -R $USER:$USER /var/www/yourdomain.net/html

Step 4.2: Create the Nginx Server Block

 

Nginx uses Server Blocks (similar to Apache Virtual Hosts). Create a new configuration file in the sites-available directory:

Bash

sudo nano /etc/nginx/sites-available/yourdomain.net

Paste the following minimal, secure configuration (replace yourdomain.net everywhere):

Nginx

server {
    listen 80;
    listen [::]:80;
    root /var/www/yourdomain.net/html;
    index index.php index.html index.htm;
    server_name yourdomain.net www.yourdomain.net;

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

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock; # Check your PHP version!
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Hide sensitive files from public access
    location ~ /\.ht {
        deny all;
    }
}

Step 4.3: Enable the Server Block and Restart Nginx

 

  1. Create a symbolic link to enable the site, and unlink the default config:

    Bash

    sudo ln -s /etc/nginx/sites-available/yourdomain.net /etc/nginx/sites-enabled/
    sudo unlink /etc/nginx/sites-enabled/default
    
  2. Test the Nginx configuration for syntax errors:

    Bash

    sudo nginx -t
    

    You should see: nginx: configuration file /etc/nginx/nginx.conf test is successful.

  3. Reload Nginx to apply the changes:

    Bash

    sudo systemctl reload nginx
    

Final Test: The PHP Info File

 

Create a temporary info.php file in your web root to confirm PHP is working through Nginx:

Bash

echo "<?php phpinfo(); ?>" | sudo tee /var/www/yourdomain.net/html/info.php

Now, navigate to http://yourdomain.net/info.php in your browser. If you see the detailed PHP information page, your LEMP stack is fully functional and securely configured!

Security Cleanup: Remember to immediately delete the info.php file when done testing!

Bash

sudo rm /var/www/yourdomain.net/html/info.php

You have successfully installed and secured a high-performance LEMP stack.

More: https://gratisvps.net/blog/the-essential-50-point-checklist-for-a-hardened-free-vps-installation/

Index