Why Install LEMP on a Virtual Server?
If you have recently purchased a virtual server (VPS) running Ubuntu or Debian, the first step to launching a website is likely installing a web software stack. While LAMP (Linux, Apache, MySQL, PHP) was the standard for years, today installing LEMP (Linux, Nginx, MySQL, PHP-FPM) is a smarter choice for virtual servers with limited resources due to Nginx's superior performance in handling concurrent connections and lower resource consumption.
In this guide, we assume you have a virtual server with Ubuntu 22.04 LTS and root access or a user with sudo privileges. You can run all commands in order and, by the end, you will have a fully functional web server with PHP and MySQL support.
Prerequisites and Initial Preparation
Before starting the LEMP installation, make sure your operating system is up to date and basic tools are installed:
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl wget git unzip
Also, verify that ports 80 and 443 are open. If you are using the UFW firewall, run the following commands:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Important Note: If you are connected to the server via SSH, be sure to add the OpenSSH rule before enabling the firewall; otherwise, you will lose your connection.
Step 1: Installing Nginx
Nginx acts as the primary web server in the LEMP stack. Installing it is straightforward:
sudo apt install -y nginx
After installation, enable and start the service:
sudo systemctl enable nginx
sudo systemctl start nginx
To ensure it is running correctly, enter your server's IP address in a browser. You should see the default Nginx page. If the page does not display, check the service status:
sudo systemctl status nginx
If there are errors, check the logs in /var/log/nginx/error.log.
Basic Nginx Security Settings
To enhance security, edit the main configuration file:
sudo nano /etc/nginx/nginx.conf
In the http section, add or modify the following lines:
server_tokens off;
client_max_body_size 10M;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
These settings hide Nginx version information, limit upload size, and add important security headers. After applying the changes, test the configuration and restart the service:
sudo nginx -t
sudo systemctl reload nginx
Step 2: Installing MySQL
In this guide, we use MySQL as the database management system. Installation:
sudo apt install -y mysql-server
After installation, run the security script:
sudo mysql_secure_installation
This script asks several questions: setting up the VALIDATE PASSWORD PLUGIN (it is recommended to choose option 2), changing the root password, removing anonymous users, disabling remote root login, and removing test databases. Answer "Y" to all questions.
Creating a Dedicated Database User
Instead of using the root user for web applications, create a dedicated user:
sudo mysql
Then, in the MySQL environment:
CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'YourStrongPassword!';
CREATE DATABASE wordpress_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wordpress'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Common Error: If you encounter the error "Access denied for user root" when running mysql_secure_installation, it is because in newer MySQL versions, the root user uses auth_socket authentication by default. To fix this, first log in with sudo mysql, then:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'NewRootPassword';
FLUSH PRIVILEGES;
EXIT;
Step 3: Installing PHP-FPM
PHP-FPM (FastCGI Process Manager) handles the processing of PHP code and works well with Nginx. To install PHP and commonly used extensions:
sudo apt install -y php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl
After installation, enable the PHP-FPM service:
sudo systemctl enable php8.1-fpm
sudo systemctl start php8.1-fpm
Note that the PHP version may vary depending on your operating system's repositories (e.g., php8.1-fpm on Ubuntu 22.04). Find the exact version with the following command:
php -v
Configuring PHP-FPM for Security
Edit the main configuration file:
sudo nano /etc/php/8.1/fpm/php.ini
Find and change the following values:
upload_max_filesize = 20M
post_max_size = 20M
max_execution_time = 60
memory_limit = 128M
expose_php = Off
The expose_php = Off setting removes PHP version information from HTTP headers. After applying the changes, restart the service:
sudo systemctl restart php8.1-fpm
Step 4: Configuring Nginx to Work with PHP
Now we need to create a server block for your website. First, create the directory structure:
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com/html
sudo chmod -R 755 /var/www/example.com
Then, create a test PHP file:
echo "<?php phpinfo(); ?>" | sudo tee /var/www/example.com/html/index.php
Now, create the Nginx configuration file:
sudo nano /etc/nginx/sites-available/example.com
Enter the following content:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
This configuration routes PHP requests to the PHP-FPM socket and blocks access to hidden files such as .htaccess.
Now, enable the server block:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Common Error: PHP File Downloads Instead of Executing
If your browser downloads the PHP file instead of executing it, it means Nginx cannot forward the request to PHP-FPM. Possible reasons:
- The socket path in the configuration is incorrect. Check the correct path with
sudo ls /var/run/php/. - The PHP-FPM service is not running. Check its status with
sudo systemctl status php8.1-fpm. - The
.phpextension is not defined in thelocationblock.
Step 5: Enabling SSL with Let's Encrypt
For better security and improved Google ranking, be sure to enable SSL. First, install Certbot:
sudo apt install -y certbot python3-certbot-nginx
Then, issue the certificate:
sudo certbot --nginx -d example.com -d www.example.com
Certbot will automatically modify the Nginx configuration and enable HTTP to HTTPS redirect. To ensure automatic certificate renewal:
sudo certbot renew --dry-run
Note: If your domain is not yet connected to the server (DNS not configured), first add the A records in your domain management panel; otherwise, certificate issuance will fail.
Step 6: Final Testing and Optimization
After completing the LEMP installation, remove the test PHP file:
sudo rm /var/www/example.com/html/index.php
To test performance, you can use the ab (Apache Bench) tool:
sudo apt install -y apache2-utils
ab -n 1000 -c 100 https://example.com/
This command sends 1000 concurrent requests and displays response statistics. If the numbers are not satisfactory, apply the following settings in /etc/nginx/nginx.conf:
worker_processes auto;
worker_connections 1024;
keepalive_timeout 65;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Conclusion
In this guide, you have completed the full steps of installing LEMP on a virtual server with a focus on security and performance. You now have an Nginx web server with PHP-FPM and MySQL support that can host dynamic websites, WordPress, or custom applications. If you are looking for a stable platform to host your projects, virtual servers with dedicated resources and technical support can be a suitable choice; however, the most important aspect is regular maintenance and continuous updates of the installed software.
For further learning, I recommend studying the official Nginx and MySQL documentation and don't forget firewall settings and regular backups. If you encounter errors at any stage, check the logs in /var/log/nginx/ and /var/log/mysql/; the solution is usually found there.