Installing a LEMP stack on your VPS

A complete tutorial on installing LEMP on a virtual server, including Nginx, MySQL, and PHP-FPM setup with basic security configurations, troubleshooting common errors, and performance optimization.

6 min Updated 18 Aug 2026

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 .php extension is not defined in the location block.

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.

Was this page helpful?