How to Install LEMP Stack (Nginx, MariaDB, PHP) on Ubuntu 25.04

LEMP Stack is a combination of free, open source software. The acronym LEMP refers to the first letters of Linux (Operating system), Nginx Server, MySQL (database software), and PHP, PERL or Python, principal components to build a viable general purpose web server.

Updating the system

We first update the system to make sure that all our installed packages are up to date. Your Ubuntu system can be updated easily with the following command.

apt update
apt upgrade

Install Nginx

Start by installation of the Nginx web server. to complete the installation, use the below commands.

apt install nginx

Output:

root@vps:~# apt install nginx -y
Installing:                     
  nginx

Installing dependencies:
  nginx-common

Suggested packages:
  fcgiwrap  nginx-doc  ssl-cert

Summary:
  Upgrading: 0, Installing: 2, Removing: 0, Not Upgrading: 0
  Download size: 741 kB
  Space needed: 2,108 kB / 96.8 GB available

Once the installation is complete, enable Nginx (to start automatically upon system boot), start the webserver, and verify the status using the commands below.

systemctl start nginx

systemctl enable nginx

systemctl status nginx

Output:

root@vps:~# systemctl status nginx
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Sat 2025-05-03 14:19:25 UTC; 18s ago
 Invocation: 826ae27de9294b1a818a4b3578d19fcd
       Docs: man:nginx(8)
   Main PID: 2262 (nginx)
      Tasks: 7 (limit: 6395)
     Memory: 5.9M (peak: 14.5M)
        CPU: 164ms
     CGroup: /system.slice/nginx.service
             ├─2262 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─2264 "nginx: worker process"
             ├─2265 "nginx: worker process"
             ├─2266 "nginx: worker process"
             ├─2267 "nginx: worker process"
             ├─2268 "nginx: worker process"
             └─2269 "nginx: worker process"

Check the Nginx version,

nginx -v

Output:

root@vps:~# nginx -v
nginx version: nginx/1.26.3 (Ubuntu)

We need to make the user Nginx the owner of the web directory. By default, it’s owned by the root user.

chown www-data:www-data /usr/share/nginx/html -R

Verify that the webserver is running and accessible by accessing your server’s IP address. From your browser,

http://IP_address

Note: Replace the4 IP_address with your actual IP Addre

image

Install MariaDB Server

MariaDB is a popular database server. The installation is simple and requires just a few steps as shown.

apt install mariadb-server mariadb-client mariadb-client-compat

Output:

root@vps:~# apt install mariadb-server mariadb-client mariadb-client-compat -y
Installing:                     
  mariadb-client  mariadb-client-compat  mariadb-server

Installing dependencies:
  galera-4                 libdbi-perl            libhtml-tagset-perl     libmariadb3          mariadb-plugin-provider-bzip2   mysql-common
  libcgi-fast-perl         libencode-locale-perl  libhtml-template-perl   libtimedate-perl     mariadb-plugin-provider-lz4     pv
  libcgi-pm-perl           libfcgi-bin            libhttp-date-perl       liburi-perl          mariadb-plugin-provider-lzma    socat
  libclone-perl            libfcgi-perl           libhttp-message-perl    liburing2            mariadb-plugin-provider-lzo
  libconfig-inifiles-perl  libfcgi0t64            libio-html-perl         mariadb-client-core  mariadb-plugin-provider-snappy
  libdbd-mariadb-perl      libhtml-parser-perl    liblwp-mediatypes-perl  mariadb-common       mariadb-server-core

Once the installation is complete, enable MariaDB (to start automatically upon system boot), start the MariaDB, and verify the status using the commands below.

systemctl start mariadb

systemctl enable mariadb

systemctl status mariadb

Output:

root@vps:~# systemctl status mariadb
● mariadb.service - MariaDB 11.4.5 database server
     Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; preset: enabled)
     Active: active (running) since Sat 2025-05-03 14:28:36 UTC; 17min ago
 Invocation: 7d7c973586874d2a98be86f22f8b54ab
       Docs: man:mariadbd(8)
             https://mariadb.com/kb/en/library/systemd/
   Main PID: 3276 (mariadbd)
     Status: "Taking your SQL requests now..."
      Tasks: 9 (limit: 42209)
     Memory: 166.3M (peak: 256.6M)
        CPU: 15.962s
     CGroup: /system.slice/mariadb.service
             └─3276 /usr/sbin/mariadbd

Secure your MariaDB installation by removing vulnerabilities and setting essential restrictions.

mysql_secure_installation

This script helps you improve the security of your MariaDB server by:

Setting a root password (if not already set).

Removing anonymous users – disallows anyone from logging in without a user account.

Disabling remote root login – root should only connect locally for better security.

Removing the test database – used for testing, can be a potential security risk.

Reloading privilege tables – applies all changes immediately.

You can run it anytime if you need to re-secure your installation.

Output:

root@server:~# mysql_secure_installation
/usr/bin/mysql_secure_installation: Deprecated program name. It will be removed in a future release, use 'mariadb-secure-installation' instead

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] y
Enabled successfully!
Reloading privilege tables..
 ... Success!

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] y
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Once secured, you can login to the MySQL using below command,

mysql -u root -p

To exit from MariaDB.

exit

Check MySQL Version,

mysql --version

Output:

root@vps:~# mysql --version
mysql from 11.4.5-MariaDB, client 15.2 for debian-linux-gnu (x86_64) using  EditLine wrapper

Install PHP

PHP 8.4 is the default version of PHP that would be installed on Ubuntu 25.04.

Install PHP and Required Extensions using below command,

apt install php-fpm php-cli php-common php-mysql php-curl php-gd php-mbstring php-xml php-readline php-opcache -y

Start and enable php8.4-fpm

systemctl start php8.4-fpm

systemctl enable php8.4-fpm

Check status of php8.4-fpm

systemctl status php8.4-fpm

Output:

root@vps:~# systemctl status php8.4-fpm
● php8.4-fpm.service - The PHP 8.4 FastCGI Process Manager
     Loaded: loaded (/usr/lib/systemd/system/php8.4-fpm.service; enabled; preset: enabled)
     Active: active (running) since Sat 2025-05-03 14:30:58 UTC; 38min ago
 Invocation: 392ee9170b33486dbde39c2cd3ec422f
       Docs: man:php-fpm8.4(8)
   Main PID: 13809 (php-fpm8.4)
     Status: "Processes active: 0, idle: 2, Requests: 1, slow: 0, Traffic: 0.00req/sec"
      Tasks: 3 (limit: 6395)
     Memory: 13.1M (peak: 14.5M)
        CPU: 511ms
     CGroup: /system.slice/php8.4-fpm.service
             ├─13809 "php-fpm: master process (/etc/php/8.4/fpm/php-fpm.conf)"
             ├─13811 "php-fpm: pool www"
             └─13812 "php-fpm: pool www"

Setting Up Server Blocks

You need to remove the file default, located in /etc/nginx/sites-enabled.

rm /etc/nginx/sites-enabled/default

Create new server block file under /etc/nginx/conf.d/ directory.

server {
    listen 80;
    listen [::]:80;
    server_name _;
    root /var/www/html/;
    index index.php index.html index.htm index.nginx-debian.html;

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

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

    # A long browser cache lifetime can speed up repeat visits to your page
    location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
         access_log        off;
         log_not_found     off;
         expires           360d;
   }

   # disable access to hidden files
   location ~ /\.ht {
        access_log off;
        log_not_found off;
        deny all;
   }
   }

Next, test to make sure that there are no syntax errors in any of your Nginx files.

nginx -t

Restart Nginx to enable your changes

systemctl reload nginx

Test PHP-FPM with the Nginx Web server, we need to create an info.php file in the webroot directory.

nano /var/www/html/info.php

Add the following PHP code to the file.

<?php phpinfo(); ?>

Now access http://localhost/info.php or http://yourserver-ip-address/info.php. You should see a page similar to the below one.

images

This concludes the installation of LEMP Stack on Ubuntu 25.04 server.


CrownCloud - Get a SSD powered KVM VPS at $4.5/month!
Use the code WELCOME for 10% off!

1 GB RAM / 25 GB SSD / 1 CPU Core / 1 TB Bandwidth per month

Available Locations: LAX | MIA | ATL | FRA | AMS