Cantech Knowledge Base

Your Go-To Hosting Resource

How to Install Nginx, MySQL, PHP (LEMP Stack) on Ubuntu 24.04?

Introduction

Setting up a LEMP stack, which includes Linux, Nginx, MySQL, and PHP, is a foundational step for hosting modern, dynamic web applications. This stack provides a powerful, open-source platform that’s lightweight, efficient, and widely supported across the web hosting industry.

Ubuntu with its long-term support and up-to-date packages, is an excellent choice for deploying the LEMP stack. By combining the speed of the Nginx web server with the reliability of MySQL and the flexibility of PHP, developers can build and scale robust web applications with ease.

In this guide, you’ll learn how to install and configure each component of the LEMP stack on an Ubuntu 24.04 server. We’ll walk through setting up a sample PHP application, connecting it to a MySQL database, and securing the server with an SSL certificate from Let’s Encrypt, ensuring your site is ready for production.

Prerequisites

Before getting started:

  • Set up an Ubuntu 24.04 server on Cantech.
  • Create an A record for your domain (e.g., app.example.com) pointing to your server’s public IP.
  • Connect via SSH as a non-root user with sudo privileges.
  • Update your server packages:
sudo apt update
sudo apt upgrade -y

Step 1: Install Nginx Web Server

Install Nginx web server to host fast and secure websites on Ubuntu.

sudo apt install nginx -y

Once the installation is complete, enable Nginx to start automatically at system boot using the command below.

sudo systemctl enable nginx

Next, start the Nginx service using the following command:

sudo systemctl start nginx

Verify Nginx status:

sudo systemctl status nginx

You should see output confirming that the service is active and running.

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2025-10-15 10:24:17 UTC; 5min ago
       Docs: man:nginx(8)
   Main PID: 1245 (nginx)
      Tasks: 3 (limit: 1152)
     Memory: 5.8M
        CPU: 110ms
     CGroup: /system.slice/nginx.service
             ├─1245 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             ├─1246 nginx: worker process
             └─1247 nginx: worker process

Step 2: Installing MySQL

Install the most recent version of the MySQL database server on your system.

sudo apt install mysql-server -y

Start running the MySQL service.

sudo systemctl start mysql

Enable the MySQL service to automatically start on system boot.

sudo systemctl enable mysql

Verify MySQL status:

sudo systemctl status mysql

Output:

● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-10-15 11:25:43 UTC; 1min 32s ago
   Main PID: 1432 (mysqld)
     Status: "Server is operational"
      Tasks: 38 (limit: 9442)
     Memory: 364.8M
        CPU: 1.482s
     CGroup: /system.slice/mysql.service
             └─1432 /usr/sbin/mysqld

Run the MySQL secure installation tool to remove unsafe default settings and improve your database security.

sudo mysql_secure_installation

Recommended prompts:

  • Enable the VALIDATE PASSWORD plugin.
  • Choose STRONG policy (2).
  • Remove anonymous users.
  • Disallow remote root login.
  • Remove the test database.
  • Reload privilege tables.

Open the MySQL console and create a new password for the root user.

sudo mysql

Set a strong password and update authentication method:

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_secure_password';

Refresh the MySQL privilege tables to make the changes effective.

mysql> FLUSH PRIVILEGES;

 Leave the MySQL console.

mysql> exit

 Restart MySQL:

sudo systemctl restart mysql

Step 3: Installing PHP

 Ubuntu 24.04 includes PHP 8.4 in its repository, offering slight performance improvements over PHP 8.3. Use the command below to install PHP 8.4 along with common extensions.

sudo apt install php8.4 php8.4-fpm php8.4-mysql php8.4-cli -y

The above command installs the following PHP modules:

  • php-mysql: Allows PHP to communicate with the MySQL database and execute SQL queries.
  • php-cli: Provides the PHP Command Line Interface (CLI) to run PHP scripts directly from the terminal.

Verify PHP version:

php -v

Output:

PHP 8.4.0 (cli) (built: Sep 23 2024 10:15:42) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.0, Copyright (c), by Zend Technologies

Start the PHP-FPM service for your installed version, such as PHP 8.4.

sudo systemctl start php8.4-fpm

Set PHP-FPM to automatically start when the system boots.

sudo systemctl enable php8.4-fpm

➞ Check the PHP-FPM service status to make sure it’s running properly.

sudo systemctl status php8.4-fpm

Output:

● php8.4-fpm.service - The PHP 8.4 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.4-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2025-10-15 10:25:47 UTC; 2min ago
       Docs: man:php-fpm8.4(8)
   Main PID: 15234 (php-fpm8.4)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 1112)
     Memory: 8.3M
        CPU: 95ms
     CGroup: /system.slice/php8.4-fpm.service
             ├─15234 php-fpm: master process (/etc/php/8.4/fpm/php-fpm.conf)
             ├─15235 php-fpm: pool www
             └─15236 php-fpm: pool www

Step 4: Configure PHP-FPM

Check the PHP-FPM Unix socket path using the ss command.

ss -pl | grep php

Output:

u_str LISTEN 0      128    /run/php/php8.4-fpm.sock  12345  *  1234/php-fpm: master
  • /run/php/php8.4-fpm.sock:  Shows the PHP-FPM socket path.

  • php-fpm: master: Indicates the PHP-FPM master process is active and listening.

Navigate to PHP-FPM pool config directory:

sudo cd /etc/php/8.4/fpm/pool.d/

Open the default PHP-FPM pool configuration file www.conf in a text editor like Nano.

sudo nano /etc/php/8.4/fpm/pool.d/www.conf

Check the PHP-FPM pool name to confirm it’s correctly configured.

[www]

Check that PHP-FPM runs under the www-data user.

user = www-data
group = www-data

Save and close the file.
Adjust process manager settings if needed:

  • pm.max_children = 10
  • pm.start_servers = 4
  • pm.min_spare_servers = 2
  • pm.max_spare_servers = 6
  • pm.max_requests = 500

You can adjust the PHP-FPM pool settings based on your server’s specs and resources.

Step 5: Configure Nginx to Use PHP-FPM

Create an index.php file inside your web root directory /var/www/html.

sudo touch /var/www/html/index.php

Use the below command to insert PHP info content into the file.

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

Delete default Nginx configuration file:

sudo rm /etc/nginx/sites-enabled/default
sudo rm /etc/nginx/sites-available/default

Create a new server block:

sudo nano /etc/nginx/sites-available/app.example.com.conf

Add the following configuration:

server {
    listen 80;
    server_name app.example.com;
    root /var/www/html;
    index index.php index.html;
    location / {
        try_files $uri $uri/ =404;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    }
}

Save and close the file.
Enable the new Nginx configuration. Replace app.example.com with your actual domain name.

sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/app.example.com

Check the Nginx configuration to ensure there are no errors.

sudo nginx -t

Output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart Nginx to load the updated configuration settings.

sudo systemctl restart nginx

Allow HTTP traffic through UFW:

sudo ufw allow 80/tcp

Visit http://app.example.com to confirm PHP is working.

Step 6: Secure Your Server with SSL

When setting up dynamic web applications with the LEMP stack, securing your server is essential. Make sure all components accept only internal requests on 127.0.0.1, while Nginx handles HTTP (port 80) and HTTPS (port 443) traffic. Follow the steps below to configure the UFW firewall and enable SSL certificates for secure connections.

Set Up Uncomplicated Firewall (UFW)

By default, Uncomplicated Firewall (UFW) is enabled and active on Ubuntu 24.04 Cantech servers. Use the steps below to set up UFW and permit connections to the Nginx web server.

Display all available UFW application profiles.

sudo ufw app list

Output:

Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH

Permit the Nginx Full profile to open HTTP Port 80 and HTTPS Port 443 through the firewall.

sudo ufw allow 'Nginx Full'

➞ Restart UFW to implement the firewall modifications.

sudo ufw reload

Check the firewall status to confirm that the new rules are active.

sudo ufw status

Output:

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Create Let’s Encrypt SSL Certificates

Set up the Certbot Let’s Encrypt client plugin for Nginx.

sudo apt install python3-certbot-nginx -y

Obtain and configure the SSL certificate:

sudo certbot --nginx --agree-tos --redirect --email [email protected] -d app.example.com

Test auto-renewal:

sudo certbot renew --dry-run

Restart Nginx:

sudo systemctl restart nginx

Step 7: Test the LEMP Stack with a Sample App

Nginx, MySQL, and PHP (LEMP) work together seamlessly to provide dynamic content for your web applications. Use the steps below to configure a sample application that shows a ‘Greetings from Cantech‘ message retrieved from a MySQL database on your server.
Access MySQL using the root user account

mysql -u root -p

Use the root user password you previously configured to log into the MySQL console.
Set up a new sample database named cantech_db

mysql> CREATE DATABASE cantech_db;

Select the database for use.

mysql> USE cantech_db;

Set up a new database user named db_user with a secure password.

mysql> CREATE USER 'db_user'@'localhost' IDENTIFIED BY 'strong-password';

Assign full permissions to the user for the cantech_db database.

mysql> GRANT ALL PRIVILEGES ON cantech_db. TO 'db_user'@'localhost';

Refresh the MySQL privileges table to implement the new user modifications.

mysql> FLUSH PRIVILEGES;

Set up a new table named CantechDocs with two columns: an id column serving as the primary key and a message column to store VARCHAR strings.

mysql> CREATE TABLE IF NOT EXISTS CantechDocs (id INT AUTO_INCREMENT PRIMARY KEY,  message VARCHAR(255) NOT NULL);

Add a new entry to the message column in the CantechDocs table with the text Greetings from Cantech.

mysql> INSERT INTO CantechDocs (message) VALUES ('Greetings from Cantech');

Check the table data to confirm that the new string has been added.

mysql> SELECT * from CantechDocs;

Output:

+----+------------------------+
| id | message                |
+----+------------------------+
|  1 | Greetings from Cantech |
+----+------------------------+
1 row in set (0.00 sec)

Close the MySQL console.

mysql> exit;

Generate a new test.php file in the /var/www/html/ web root directory using a text editor like Nano.

sudo nano /var/www/html/test.php

Insert the following content into the file.

<?php
$servername = "localhost";
$username = "db_user";
$password = "strong-password";
$dbname = "cantech_db";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("Database Connection Failed: " . $conn->connect_error);
}
$sql = "SELECT message FROM CantechDocs";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    $row = $result->fetch_assoc();
    echo "<h1>" . htmlspecialchars($row["message"]) . "</h1>";
} else {
    echo "<h1>No message found.</h1>";
}
$conn->close();
?>

Save and exit.

The PHP application code above establishes a connection to your MySQL database and shows the Greetings from Cantech string from your sample cantech_db database upon successful connection.

Open your domain in a new browser window using the /test.php path.

https://app.example.com/test.php

You should see:
Greetings from Cantech

Conclusion

You’ve successfully installed, configured, and secured a LEMP stack Ubuntu 24.04. With Nginx serving as the web server, MySQL managing your databases, and PHP powering dynamic content, your server is now ready to host modern web applications. Secure your stack further with strong passwords, UFW rules, and regular updates.

Related:

October 17, 2025