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:
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.
-
Check available profiles:
Bashsudo ufw app list -
Allow the Nginx Full profile (covers both HTTP on port 80 and HTTPS on port 443):
Bashsudo ufw allow 'Nginx Full' -
Verify the new firewall status:
Bashsudo ufw statusYou should see your new SSH port,
Nginx Full(or80/tcpand443/tcp), and theOpenSSHrule listed as allowed.
Step 1.3: Test Nginx Installation
Verify Nginx is active and running, then check its default page.
-
Check Nginx service status:
Bashsudo systemctl status nginxThe output should show
Active: active (running). -
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
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.
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.
sudo mysql
Inside the MariaDB shell, run the following commands, replacing the bold text:
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:
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):
sudo nano /etc/php/8.3/fpm/php.ini
Find the line ;cgi.fix_pathinfo=1 and change it to:
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:
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:
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:
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:
sudo nano /etc/nginx/sites-available/yourdomain.net
Paste the following minimal, secure configuration (replace yourdomain.net everywhere):
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
-
Create a symbolic link to enable the site, and unlink the default config:
Bashsudo ln -s /etc/nginx/sites-available/yourdomain.net /etc/nginx/sites-enabled/ sudo unlink /etc/nginx/sites-enabled/default -
Test the Nginx configuration for syntax errors:
Bashsudo nginx -tYou should see:
nginx: configuration file /etc/nginx/nginx.conf test is successful. -
Reload Nginx to apply the changes:
Bashsudo 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:
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!
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/

