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):
sudo apt install ufw
sudo ufw allow 80/tcp
sudo ufw allow 443/tcpAlmaLinux/Rocky (firewalld):
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:
sudo apt update
sudo apt install nginxAlmaLinux/Rocky:
sudo dnf install nginxEnable and start nginx:
sudo systemctl enable --now nginxOpen http://SERVER_IP/ in a browser — you should see nginx's default page.
Step 2. Install and configure MariaDB
Ubuntu/Debian:
sudo apt install mariadb-serverAlmaLinux/Rocky:
sudo dnf install mariadb-serverEnable autostart, start MariaDB, and run through the basic security setup:
sudo systemctl enable --now mariadb
sudo mysql_secure_installationThe 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:
sudo mysql -e "SELECT VERSION();"Step 3. Install PHP-FPM
Ubuntu/Debian:
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:
sudo dnf install php-fpm php-mysqlndEnable and start PHP-FPM. On Ubuntu/Debian, substitute your PHP version for 8.3:
sudo systemctl enable --now php8.3-fpmOn AlmaLinux/Rocky, the PHP version doesn't affect the service name:
sudo systemctl enable --now php-fpmStep 4. Connect PHP-FPM to nginx
Ubuntu/Debian. Open the default site file:
sudo nano /etc/nginx/sites-available/defaultand add this inside the existing server { ... } block (replace 8.3 with your PHP version):
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:
sudo nano /etc/nginx/conf.d/default.conflocation ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/run/php-fpm/www.sock;
}Test the configuration and reload nginx:
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:
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginxThen restart PHP-FPM:
sudo systemctl restart php-fpmStep 5. Create a test PHP page and check the result
Ubuntu/Debian:
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php > /dev/nullAlmaLinux/Rocky:
echo '<?php phpinfo(); ?>' | sudo tee /usr/share/nginx/html/info.php > /dev/nullOpen 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:
sudo rm /var/www/html/info.phpAlmaLinux/Rocky:
sudo rm /usr/share/nginx/html/info.phpPart 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:
sudo apt update
sudo apt install apache2AlmaLinux/Rocky:
sudo dnf install httpdEnable autostart and start the web server.
Ubuntu/Debian:
sudo systemctl enable --now apache2AlmaLinux/Rocky:
sudo systemctl enable --now httpdOpen 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:
sudo apt install mariadb-serverAlmaLinux/Rocky:
sudo dnf install mariadb-serversudo systemctl enable --now mariadb
sudo mysql_secure_installationStep 3. Install PHP
Ubuntu/Debian:
sudo apt install php libapache2-mod-php php-mysqlAlmaLinux/Rocky:
sudo dnf install php php-mysqlndThe 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:
sudo systemctl restart apache2AlmaLinux/Rocky:
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:
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php > /dev/nullOpen 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.
sudo rm /var/www/html/info.phpWhat'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".