TutorialsAugust 4, 20264 min read

How to Set Up a LEMP Stack (Linux, Nginx, MySQL, PHP)

Build a complete LEMP stack on Ubuntu 24.04 — Nginx, MySQL, and PHP-FPM — and serve a working PHP site with clean, correct config.

NBy Nxeon

LEMP is the modern web stack: Linux, Nginx (the "E" is for its pronunciation, engine-x), MySQL, and PHP. It powers WordPress, Laravel, and countless PHP applications, using less memory than the older Apache-based LAMP stack. This guide builds a complete LEMP stack on Ubuntu 24.04 and serves a working PHP page.

The four pieces

  • Linux: your Ubuntu 24.04 VPS.
  • Nginx: the web server, handling requests and static files.
  • MySQL: the database.
  • PHP-FPM: a fast PHP process manager Nginx talks to over a socket.

Unlike Apache, Nginx does not embed PHP — it hands PHP requests to PHP-FPM. That separation is what makes LEMP lean.

Install Nginx

sudo apt update
sudo apt install nginx -y
sudo ufw allow 'Nginx Full'

If you want the full walkthrough, see installing Nginx on Ubuntu 24.04.

Install MySQL

sudo apt install mysql-server -y
sudo mysql_secure_installation

Work through the security prompts as described in our MySQL install and secure guide, then create an app database and user for your site.

Install PHP-FPM

Install PHP-FPM and the MySQL driver:

sudo apt install php-fpm php-mysql -y

Check which version installed (Ubuntu 24.04 ships PHP 8.3):

php -v
systemctl status php8.3-fpm

Note the socket path — it will be /run/php/php8.3-fpm.sock.

The Nxeon game-server control panel — live console, player slots, and TPS
The Nxeon game-server control panel — live console, player slots, and TPS

Configure Nginx to process PHP

Create a web root and an Nginx server block that passes .php files to PHP-FPM. Make the root:

sudo mkdir -p /var/www/example.com
sudo chown -R www-data:www-data /var/www/example.com

Create /etc/nginx/sites-available/example.com:

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

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

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

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

The location ~ \.php$ block is the heart of it — it forwards PHP execution to the FPM socket. Adjust the version in the socket path if yours differs. Enable and reload:

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

Test PHP processing

Drop a test file:

echo '<?php phpinfo();' | sudo tee /var/www/example.com/info.php

Visit http://example.com/info.php and you should see the PHP info page. Delete it afterwards — it leaks server details:

sudo rm /var/www/example.com/info.php

Add HTTPS and go live

Point your domain at the server (how to point a domain to your VPS) and add a free certificate with Certbot. Your LEMP stack is now ready for WordPress, Laravel, or any PHP app.

Tune PHP-FPM and enable OPcache

PHP-FPM runs a pool of worker processes, and its defaults suit larger servers. On a small VPS, trim the pool in /etc/php/8.3/fpm/pool.d/www.conf:

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Each child uses memory, so max_children times your average PHP memory should fit comfortably in RAM. Next, make sure OPcache is on — it compiles PHP once and caches the bytecode, a large speed win. It ships enabled on Ubuntu; confirm in /etc/php/8.3/mods-available/opcache.ini:

opcache.enable=1
opcache.memory_consumption=128

Restart after changes:

sudo systemctl restart php8.3-fpm

Verify the whole stack

A quick end-to-end test: create a PHP file that connects to MySQL and prints a query result. If the page renders data, Nginx, PHP-FPM, and MySQL are all talking to each other — the three tiers of your LEMP stack confirmed working together.

FAQ

LEMP vs LAMP — what is the real difference?

LAMP uses Apache with PHP embedded via mod_php; LEMP uses Nginx with PHP handed off to PHP-FPM. LEMP typically uses less memory and handles concurrency better; LAMP is friendlier if you depend on .htaccess. See our Apache install guide for the Apache side.

Why does my browser download the PHP file instead of running it?

Nginx is not passing PHP to FPM. Check the location ~ \.php$ block exists, the fastcgi_pass socket path matches your installed PHP version, and that you reloaded Nginx.

Which PHP version ships with Ubuntu 24.04?

PHP 8.3, so the FPM socket is /run/php/php8.3-fpm.sock. If you install a different version from a PPA, update the socket path in your server block to match.

How do I raise the PHP upload limit?

Edit upload_max_filesize and post_max_size in /etc/php/8.3/fpm/php.ini, then sudo systemctl restart php8.3-fpm. Also raise client_max_body_size in your Nginx server block, since both limits apply.

Nxeon WordPress and PHP hosting on a VPS gives you full root to run LEMP exactly how you like on fast NVMe — with one-click images and free migration help to move a PHP site across.

#lemp#nginx#mysql#php#ubuntu#seobatch

Deploy your first server in under a minute

Creating an account is free and takes no card details. You pay when you deploy — choose a billing term and pay from your wallet or by card at checkout.