MHOSTMHOST

The LEMP and LAMP web stacks

LEMP and LAMP are the two most common web stacks for PHP sites: a web server, a database, and PHP working together — the foundation under almost any PHP application, from custom scripts to WordPress and other CMSes. This article covers how they differ and how to install either one on your VPS by hand, step by step, ending with a working PHP test page.

What LEMP and LAMP are

The letters in the name spell out the stack's components:

  • LEMP — Linux, nginx (pronounced "engine-x", hence the "E" instead of "A" in the name), MariaDB (or MySQL), and PHP-FPM.
  • LAMP — Linux, Apache, MySQL (or MariaDB), and PHP as an Apache module itself (mod_php).

The key technical difference is how the web server runs PHP code. nginx has no modules for executing PHP — it only serves static files and proxies requests, handing PHP files off to a separate process, PHP-FPM (FastCGI Process Manager), over a unix socket or TCP. Apache in the classic LAMP setup runs PHP right inside itself via the mod_php module — and only Apache supports .htaccess, per-directory overrides; nginx has no direct equivalent, all rules live centrally in its config.

The performance difference is usually barely noticeable for a small-to-medium site — in practice the choice is often driven by what you're already used to, or by a specific CMS's requirements (some older PHP applications are hard-wired to expect .htaccess and Apache).

Tip: you can install either stack in one click with a ready-made VMmanager 6 recipe, without typing a single command — see the "Ready-made VMmanager 6 recipes" article. The rest of this article covers installing both stacks manually — useful if you need control over package versions, extra PHP modules, or if the recipe doesn't fit for some reason.
MySQL or MariaDB? These days, practically everyone installs MariaDB for both stacks — a MySQL fork that's fully compatible with it at the protocol, SQL, and tooling level (the same mysql client, the same port 3306). Debian and Ubuntu haven't shipped a "genuine" Oracle MySQL package in their standard repositories for years — MariaDB has taken its place. So below, for both stacks, we install MariaDB specifically — that's the standard, modern "MySQL" for LAMP today.
Tip: this article is about wiring up the whole web server + database + PHP combo, on the default site. If you need a dedicated virtual host for a specific domain, several sites on one server, or a deeper dive into the web server itself — see the "Nginx: install and your first site" and "Apache: install and virtual hosts" articles.

What you'll need

  • SSH access to the VPS as root or a user with sudo.
  • One of the supported systems: Ubuntu 22.04/24.04, Debian 11/12, AlmaLinux/Rocky Linux 8/9.
  • One web stack per server. If you want to try both LEMP and LAMP, use separate servers — nginx and Apache/httpd both claim port 80 by default and won't work at the same time on one server.

Open the firewall ports

Port 80 (HTTP) is needed to open the test page from a browser; port 443 (HTTPS) will come in handy later if you add a TLS certificate.

Ubuntu/Debian (ufw):

bash
sudo apt install ufw
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

AlmaLinux/Rocky (firewalld):

bash
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Important: if ufw isn't set up on the server at all yet, go through the "Setting up the UFW firewall" article first — it allows SSH before enabling the firewall, otherwise you risk locking yourself out of the server.

Part 1. Manually installing LEMP (nginx + MariaDB + PHP-FPM)

Step 1. Install nginx

Ubuntu/Debian:

bash
sudo apt update
sudo apt install nginx

AlmaLinux/Rocky:

bash
sudo dnf install nginx

Enable and start nginx:

bash
sudo systemctl enable --now nginx

Open http://SERVER_IP/ in a browser — you should see nginx's default page.

Step 2. Install and configure MariaDB

Ubuntu/Debian:

bash
sudo apt install mariadb-server

AlmaLinux/Rocky:

bash
sudo dnf install mariadb-server

Enable autostart, start MariaDB, and run through the basic security setup:

bash
sudo systemctl enable --now mariadb
sudo mysql_secure_installation

The mysql_secure_installation script asks a few questions: set a root password, remove anonymous users, disallow remote root login, and remove the test database. You can answer Y to all of them — those are safe defaults.

Check that the server responds:

bash
sudo mysql -e "SELECT VERSION();"

Step 3. Install PHP-FPM

Ubuntu/Debian:

bash
sudo apt install php-fpm php-mysql
ls /etc/php/

The ls /etc/php/ command shows the installed PHP version (for example, 8.3) — you'll need it for the service and socket name in the next step.

AlmaLinux/Rocky:

bash
sudo dnf install php-fpm php-mysqlnd

Enable and start PHP-FPM. On Ubuntu/Debian, substitute your PHP version for 8.3:

bash
sudo systemctl enable --now php8.3-fpm

On AlmaLinux/Rocky, the PHP version doesn't affect the service name:

bash
sudo systemctl enable --now php-fpm

Step 4. Connect PHP-FPM to nginx

Ubuntu/Debian. Open the default site file:

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

and add this inside the existing server { ... } block (replace 8.3 with your PHP version):

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

AlmaLinux/Rocky. The same block, but in a different file and with a different socket path:

bash
sudo nano /etc/nginx/conf.d/default.conf
nginx
location ~ \.php$ {
    include fastcgi.conf;
    fastcgi_pass unix:/run/php-fpm/www.sock;
}

Test the configuration and reload nginx:

bash
sudo nginx -t && sudo systemctl reload nginx
AlmaLinux/Rocky only: the stock PHP-FPM pool is configured for the apache user by default, not nginx — so nginx will get "Permission denied" when it tries to reach the socket. Open /etc/php-fpm.d/www.conf and set these four lines to:
ini
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx

Then restart PHP-FPM:

bash
sudo systemctl restart php-fpm

Step 5. Create a test PHP page and check the result

Ubuntu/Debian:

bash
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php > /dev/null

AlmaLinux/Rocky:

bash
echo '<?php phpinfo(); ?>' | sudo tee /usr/share/nginx/html/info.php > /dev/null

Open http://SERVER_IP/info.php in a browser. You should see a page with PHP information: the Server API row should read FPM/FastCGI (confirming PHP is running through PHP-FPM), and the mysqli / pdo_mysql sections should show the MariaDB driver is loaded.

Done: if the page loads and shows FPM/FastCGI, LEMP is set up and working.
Important: phpinfo() reveals detailed server information — versions, paths, environment variables. Don't leave this page publicly reachable — delete the file right after testing.

Ubuntu/Debian:

bash
sudo rm /var/www/html/info.php

AlmaLinux/Rocky:

bash
sudo rm /usr/share/nginx/html/info.php

Part 2. Manually installing LAMP (Apache + MySQL + PHP)

If LEMP from Part 1 is already set up on this same server, stop nginx first to free up port 80 for Apache: sudo systemctl disable --now nginx.

Step 1. Install Apache

Ubuntu/Debian:

bash
sudo apt update
sudo apt install apache2

AlmaLinux/Rocky:

bash
sudo dnf install httpd

Enable autostart and start the web server.

Ubuntu/Debian:

bash
sudo systemctl enable --now apache2

AlmaLinux/Rocky:

bash
sudo systemctl enable --now httpd

Open http://SERVER_IP/ in a browser — you should see Apache's default welcome page.

Step 2. Install and configure MariaDB (MySQL)

If MariaDB is already installed and configured — say, you already did Part 1 on this server — skip this step.

Ubuntu/Debian:

bash
sudo apt install mariadb-server

AlmaLinux/Rocky:

bash
sudo dnf install mariadb-server
bash
sudo systemctl enable --now mariadb
sudo mysql_secure_installation

Step 3. Install PHP

Ubuntu/Debian:

bash
sudo apt install php libapache2-mod-php php-mysql

AlmaLinux/Rocky:

bash
sudo dnf install php php-mysqlnd

The libapache2-mod-php package enables the PHP module in Apache automatically; on AlmaLinux/Rocky, the php package adds the httpd config itself (/etc/httpd/conf.d/php.conf) if httpd is already installed — which is why it matters to install Apache before PHP, as in this article. All that's left is to restart the web server.

Ubuntu/Debian:

bash
sudo systemctl restart apache2

AlmaLinux/Rocky:

bash
sudo systemctl restart httpd
Tip: if the browser offers to download the .php file instead of running it, the PHP module didn't get wired up. On Ubuntu/Debian, check /etc/apache2/mods-enabled/php*.conf (if it's missing, enable the module with a2enmod phpX.Y, substituting your version, and restart Apache); on AlmaLinux/Rocky, check that /etc/httpd/conf.d/php.conf exists — if not, reinstall the php package after httpd.

Step 4. Create a test PHP page and check the result

The path is the same on every system — Apache's standard DocumentRoot:

bash
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php > /dev/null

Open http://SERVER_IP/info.php in a browser. The Server API row should read Apache 2.0 Handler (the mod_php module inside Apache itself — as opposed to FPM/FastCGI for LEMP), and the mysqli / pdo_mysql sections should show the MariaDB driver is loaded.

Done: if the page loads and shows Apache 2.0 Handler, LAMP is set up and working.
Important: delete the test page right after checking it — phpinfo() reveals server details that shouldn't stay publicly reachable.
bash
sudo rm /var/www/html/info.php

What's next

From here you'd typically set up a domain and a virtual host for a specific site — see the "Nginx: install and your first site" and "Apache: install and virtual hosts" articles — and, for a production project, add an HTTPS certificate. If you haven't logged in to the server's control panel yet, start with "How to log in to VMmanager 6"; the full list of ready-made recipes is in "Ready-made VMmanager 6 recipes".