Install LEMP Stack on Ubuntu VPS — Nginx, MySQL, PHP-FPM setup guide

A LEMP Stack is one of the most popular web server setups for running dynamic websites and applications on a Linux VPS. The acronym stands for Linux, Enginx (pronounced "engine-x"), MySQL, and PHP — four open-source technologies that work together to deliver fast, scalable web hosting.

This guide walks you through installing a complete LEMP Stack on Ubuntu 22.04 LTS, from the initial system update to SSL certificate installation and performance optimization. Every step is tested and ready to follow on any VPS with root or sudo access.

1. What is a LEMP Stack? Nginx vs Apache Comparison

LEMP Stack replaces Apache with Nginx as the web server component. This seemingly small change has significant performance implications:

Feature Nginx (LEMP) Apache (LAMP)
Connection Model Event-driven, non-blocking Process/thread per request
Memory Usage Low, stable under load Grows with connections
Static File Serving Very fast Good
PHP Execution Via PHP-FPM (separate process) mod_php (built-in)
Best For VPS with limited RAM, high traffic Sites relying heavily on .htaccess

Nginx's event-driven architecture allows it to handle thousands of simultaneous connections with minimal memory — making it ideal for VPS environments where resources are shared or limited.

2. Prerequisites Before You Begin

Ensure you have the following ready before starting the installation:

Note: AsiaGB VPS plans start at 500 THB/month with Ubuntu 22.04 LTS support, Full Root Access, and SSD storage. All plans include Uptime 99% SLA and can run LEMP Stack immediately after setup.

3. Update the System

SSH into your VPS and update the package index and installed packages:

sudo apt update && sudo apt upgrade -y

This may take 2–5 minutes. If prompted about configuration files during the upgrade, choose to keep the existing version unless you know specifically why you need the new one.

4. Install and Configure Nginx

Install Nginx from the official Ubuntu repository:

sudo apt install nginx -y

Enable Nginx to start on boot and start the service:

sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx

If the status shows active (running), Nginx is working. Open a browser and navigate to your VPS IP — you should see the "Welcome to nginx!" page.

Configure UFW Firewall

Open only the necessary ports:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

⚠️ Important: Always allow OpenSSH before enabling UFW. If you forget, you'll be locked out of your VPS immediately. Use your VPS provider's console to recover if this happens.

5. Install MySQL and Run Secure Installation

Install the MySQL server package:

sudo apt install mysql-server -y

Run the security script to harden your MySQL installation:

sudo mysql_secure_installation

The script will ask you to:

Create a Dedicated Database User

Create a separate MySQL user for each website instead of using root:

sudo mysql

-- Create the database
CREATE DATABASE mywebsite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create a dedicated user
CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'StrongPasswordHere';

-- Grant permissions
GRANT ALL PRIVILEGES ON mywebsite.* TO 'webuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

6. Install PHP and PHP-FPM

Ubuntu 22.04 includes PHP 8.1 in its default repositories. Install PHP-FPM and common extensions:

sudo apt install php8.1-fpm php8.1-mysql php8.1-curl php8.1-gd \
  php8.1-mbstring php8.1-xml php8.1-zip php8.1-bcmath \
  php8.1-imagick php8.1-intl -y

Verify PHP-FPM is running:

sudo systemctl status php8.1-fpm

Tune PHP Configuration

Edit the FPM php.ini for better performance:

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

Find and update these values:

upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
memory_limit = 256M
max_input_vars = 3000

Restart PHP-FPM to apply changes:

sudo systemctl restart php8.1-fpm

7. Connect Nginx to PHP-FPM

Edit the default Nginx server block to enable PHP processing:

sudo nano /etc/nginx/sites-available/default

Add the PHP location block:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/html;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

Test the configuration and reload Nginx:

sudo nginx -t
sudo systemctl reload nginx

8. Configure Nginx Server Blocks (Virtual Hosts)

For multiple domains on the same VPS, create separate server blocks:

sudo mkdir -p /var/www/example.com/public_html
sudo chown -R $USER:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com

Create a new configuration file:

sudo nano /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    root /var/www/example.com/public_html;
    index index.php index.html;

    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|webp|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

Enable the site and reload Nginx:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

9. Test PHP Processing

Create a PHP info file to verify PHP is processing correctly:

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

Open http://YOUR_VPS_IP/phpinfo.php in a browser. You should see a detailed PHP information page confirming the LEMP Stack is fully operational.

⚠️ Delete phpinfo.php immediately after testing: This file exposes sensitive server configuration details. Never leave it on a production server.

sudo rm /var/www/html/phpinfo.php

10. Install SSL with Let's Encrypt (Certbot)

Let's Encrypt provides free SSL certificates. Install Certbot with the Nginx plugin:

sudo apt install certbot python3-certbot-nginx -y

Obtain and install a certificate for your domain:

sudo certbot --nginx -d example.com -d www.example.com

Certbot will ask for your email, accept terms, and configure Nginx to use HTTPS automatically. Choose to redirect HTTP to HTTPS when prompted.

Test Auto-Renewal

sudo certbot renew --dry-run

If no errors appear, auto-renewal is configured correctly. Certificates will renew automatically 30 days before expiry.

💡 Tip: AsiaGB also offers paid SSL certificates (OV, EV, Wildcard) for businesses needing organization validation or wildcard subdomain coverage. Prices start at 1,000 THB/year.

11. Performance Optimization Tips

After completing the base installation, apply these optimizations:

Enable Nginx Gzip Compression

Add to the http {} block in /etc/nginx/nginx.conf:

gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

Tune PHP-FPM Pool Settings

Edit /etc/php/8.1/fpm/pool.d/www.conf for 2 GB RAM VPS:

pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500

Optimize MySQL InnoDB Buffer Pool

Edit /etc/mysql/mysql.conf.d/mysqld.cnf:

[mysqld]
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
query_cache_size = 0
query_cache_type = 0

12. Troubleshooting Common Issues

Issue Solution
502 Bad Gateway PHP-FPM not running: sudo systemctl restart php8.1-fpm
403 Forbidden Permissions issue: sudo chown -R www-data:www-data /var/www/html
PHP files download instead of execute Missing location ~ \.php$ block or incorrect socket path
MySQL connection refused Verify credentials: mysql -u webuser -p
Nginx won't start after config change sudo nginx -t to view specific config errors

13. Frequently Asked Questions

What is a LEMP Stack and how does it differ from LAMP?

LEMP Stack uses Nginx (N/E for Engine-x) instead of Apache (A) in LAMP. Nginx's event-driven, non-blocking I/O model handles more concurrent connections with less memory. It's particularly effective on VPS servers where RAM is limited. LAMP may be preferable when you need extensive .htaccess support.

What VPS specs do I need to run a LEMP Stack?

You need at minimum 1 GB RAM and 1 CPU core for a basic LEMP Stack with one website. For WordPress with moderate traffic, 2 GB RAM is recommended. AsiaGB VPS plans start at 500 THB/month with SSD storage and full root access — perfectly suited for LEMP Stack deployments.

Why does Nginx need PHP-FPM while Apache does not?

Nginx is designed as a pure HTTP server and doesn't execute application code internally. PHP-FPM runs as a separate process pool that Nginx communicates with via FastCGI protocol. This separation means each component can be independently scaled and configured, leading to better resource utilization.

Can I run WordPress on a LEMP Stack?

Absolutely. WordPress is fully compatible with Nginx and PHP-FPM. After setting up LEMP, create a MySQL database, download WordPress, extract it to your server root, and configure the Nginx server block with try_files $uri $uri/ /index.php?$args; for WordPress permalink support.

Do I need to configure UFW firewall after installing LEMP?

Yes, always configure a firewall. Open only port 22 (SSH), 80 (HTTP), and 443 (HTTPS). The commands are: sudo ufw allow OpenSSH && sudo ufw allow 'Nginx Full' && sudo ufw enable. Never enable UFW without first allowing SSH or you'll be locked out.

Is mysql_secure_installation really necessary?

Yes, it's essential. Out of the box, MySQL has anonymous user accounts and a test database that create security vulnerabilities. The secure installation script removes these risks by deleting anonymous users, disabling remote root login, and dropping the test database — all critical steps for any internet-facing server.

Start Your LEMP Stack VPS Today

AsiaGB VPS from 500 THB/month — Full Root Access, SSD Storage, 99% Uptime. Thailand and Singapore locations available.

View VPS Plans