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

Updated on 24 April, 2026
Install and configure the LEMP stack with Nginx, MySQL, and PHP on an Ubuntu 26.04 server for hosting dynamic web applications and services.
How to Install Nginx, MySQL, PHP (LEMP Stack) on Ubuntu 26.04 header image

LEMP is a web application stack consisting of Linux, Nginx, MySQL, and PHP. Nginx handles HTTP requests and serves static content, MySQL stores and manages relational data, and PHP processes server-side logic to generate dynamic web pages. Together, these components form a complete platform for hosting web applications such as content management systems, e-commerce platforms, and custom web services.

This article explains how to install the LEMP stack on an Ubuntu 26.04 server. It covers setting up each component, configuring Nginx to process PHP requests through PHP-FPM, securing the server with firewall rules and a Let's Encrypt SSL certificate, and testing the stack with a sample PHP application that queries a MySQL database.

Prerequisites

Before you begin, you need to:

Install Nginx

Nginx is available in the default Ubuntu 26.04 APT repositories. The following steps install the web server and verify that the service is running.

  1. Update the APT package index.

    console
    $ sudo apt update
    
  2. Install Nginx.

    console
    $ sudo apt install nginx -y
    
  3. Enable Nginx to start automatically at boot time.

    console
    $ sudo systemctl enable nginx
    
  4. Start the Nginx service.

    console
    $ sudo systemctl start nginx
    
  5. Verify that Nginx is active and running.

    console
    $ sudo systemctl status nginx
    

    The output should display active (running), confirming that Nginx is operational.

Install MySQL

MySQL is included in the default Ubuntu 26.04 repositories. The following steps install the database server, enable the service, and run the secure installation script to harden the default configuration.

  1. Install the MySQL server package.

    console
    $ sudo apt install mysql-server -y
    
  2. Enable MySQL to start automatically at boot time.

    console
    $ sudo systemctl enable mysql
    
  3. Start the MySQL service.

    console
    $ sudo systemctl start mysql
    
  4. Verify that MySQL is active and running.

    console
    $ sudo systemctl status mysql
    

    The output should display active (running), confirming that the MySQL server is operational.

  5. Run the MySQL secure installation script to remove insecure defaults.

    console
    $ sudo mysql_secure_installation
    

    Respond to each prompt as described below:

    • VALIDATE PASSWORD COMPONENT: Enter Y and press Enter to activate password validation.
    • Password Validation Policy: Enter 2 to require strong passwords.
    • Remove anonymous users?: Enter Y to delete anonymous database accounts.
    • Disallow root login remotely?: Enter Y to restrict root access to the local server.
    • Remove test database and access to it?: Enter Y to drop the default test database.
    • Reload privilege tables now?: Enter Y to refresh the privilege tables and apply all changes.
  6. Open the MySQL server configuration file.

    console
    $ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
    
  7. Add the following directive under the [mysqld] section to activate the mysql_native_password authentication plugin.

    ini
    mysql_native_password=ON
    

    Save and close the file.

  8. Restart MySQL to load the updated configuration.

    console
    $ sudo systemctl restart mysql
    
  9. Access the MySQL console as the root system user.

    console
    $ sudo mysql
    
  10. Set a strong password for the root account. Replace your_strong_password with a secure password that meets your validation policy.

    sql
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password';
    
  11. Reload the privilege tables to apply the password change.

    sql
    mysql> FLUSH PRIVILEGES;
    
  12. Exit the MySQL console.

    sql
    mysql> EXIT;
    

Install PHP

PHP-FPM (FastCGI Process Manager) enables Nginx to process PHP scripts by forwarding requests through a Unix socket. The following steps install PHP, PHP-FPM, and the MySQL extension required for database connectivity.

  1. Install PHP, PHP-FPM, and essential modules.

    console
    $ sudo apt install php php-fpm php-mysql php-cli -y
    

    The command installs the following packages:

    • php-fpm: Manages PHP worker processes for handling web server requests.
    • php-mysql: Enables PHP to connect to MySQL databases.
    • php-cli: Provides the PHP command-line interpreter for running scripts in the terminal.
  2. Confirm the installed PHP version.

    console
    $ php -v
    

    Your output should be similar to the one below:

    PHP 8.5.2 (cli) (built: Jan 21 2026 17:35:28) (NTS)
    Copyright (c) The PHP Group
    Built by Ubuntu
    Zend Engine v4.5.2, Copyright (c) Zend Technologies
        with Zend OPcache v8.5.2, Copyright (c), by Zend Technologies
  3. Enable PHP-FPM to start automatically at boot time.

    console
    $ sudo systemctl enable php8.5-fpm
    
  4. Start the PHP-FPM service.

    console
    $ sudo systemctl start php8.5-fpm
    
  5. Verify that PHP-FPM is active and running.

    console
    $ sudo systemctl status php8.5-fpm
    

    The output should display active (running), confirming that PHP-FPM is operational.

Set Up Firewall Rules

Uncomplicated Firewall (UFW) is active by default on Ubuntu 26.04. The following steps open ports for HTTP and HTTPS traffic so that Nginx can serve web applications.

  1. Allow HTTP traffic on port 80.

    console
    $ sudo ufw allow 80/tcp
    
  2. Allow HTTPS traffic on port 443.

    console
    $ sudo ufw allow 443/tcp
    
  3. Verify the active firewall rules.

    console
    $ sudo ufw status
    

    Your output should be similar to the one below:

    Status: active
    
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW       Anywhere
    80/tcp                     ALLOW       Anywhere
    443/tcp                    ALLOW       Anywhere
    22/tcp (v6)                ALLOW       Anywhere (v6)
    80/tcp (v6)                ALLOW       Anywhere (v6)
    443/tcp (v6)               ALLOW       Anywhere (v6)

Configure Nginx with PHP-FPM

Nginx does not process PHP scripts natively. It forwards PHP requests to PHP-FPM through a Unix socket for execution. The following steps create a virtual host configuration that connects Nginx to PHP-FPM and serves a PHP application.

  1. Unlink the default Nginx virtual host configuration.

    console
    $ sudo unlink /etc/nginx/sites-enabled/default
    
  2. Create a new virtual host configuration file. Replace app.example.com with your actual domain name.

    console
    $ sudo nano /etc/nginx/sites-available/app.example.com.conf
    
  3. Add the following configuration to the file.

    ini
    server {
        listen 80;
        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.5-fpm.sock;
        }
    }
    

    Save and close the file.

    Within the configuration:

    • server_name: Defines the domain that triggers this virtual host.
    • root: Sets the directory from which Nginx serves files.
    • location ~ \.php$: Matches requests ending in .php and forwards them to PHP-FPM.
    • include snippets/fastcgi-php.conf: Loads the predefined FastCGI directives for PHP processing.
    • fastcgi_pass: Specifies the PHP-FPM Unix socket path for communication.
  4. Enable the virtual host by creating a symbolic link.

    console
    $ sudo ln -s /etc/nginx/sites-available/app.example.com.conf /etc/nginx/sites-enabled/
    
  5. Test the Nginx configuration for syntax errors.

    console
    $ sudo nginx -t
    

    The output should confirm that the configuration syntax is ok and the test is successful.

  6. Restart Nginx to activate the virtual host.

    console
    $ sudo systemctl restart nginx
    

Secure the Server with SSL

SSL certificates encrypt communication between the client browser and the Nginx web server over HTTPS. The following steps install Certbot and generate a trusted Let's Encrypt SSL certificate for your domain.

  1. Install the Certbot Let's Encrypt client and the Nginx plugin.

    console
    $ sudo apt install certbot python3-certbot-nginx -y
    
  2. Generate an SSL certificate for your domain. Replace app.example.com with your actual domain name.

    console
    $ sudo certbot --nginx -d app.example.com --agree-tos
    

    Follow the on-screen prompts to complete the certificate generation. Certbot automatically updates the Nginx virtual host configuration to enable HTTPS.

  3. Verify that the automatic renewal process is configured correctly.

    console
    $ sudo certbot renew --dry-run
    

Test the LEMP Stack

A working LEMP stack allows PHP to query data from MySQL and return dynamic content through Nginx. The following steps create a sample database, insert a test record, and build a PHP application that retrieves and displays the data in a web browser.

  1. Log in to the MySQL console as the root user.

    console
    $ mysql -u root -p
    

    Enter the root password you configured earlier.

  2. Create a new database named example_db.

    sql
    mysql> CREATE DATABASE example_db;
    
  3. Create a database user named example_user with a strong password. Replace strong_password with your desired password.

    sql
    mysql> CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'strong_password';
    
  4. Grant the user full privileges on the example_db database.

    sql
    mysql> GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost';
    
  5. Reload the privilege tables.

    sql
    mysql> FLUSH PRIVILEGES;
    
  6. Switch to the example_db database.

    sql
    mysql> USE example_db;
    
  7. Create a table named messages with an auto-incrementing ID and a text column.

    sql
    mysql> CREATE TABLE messages (
             id INT AUTO_INCREMENT PRIMARY KEY,
             content VARCHAR(255) NOT NULL
             );
    
  8. Insert a sample record into the table.

    sql
    mysql> INSERT INTO messages (content) VALUES ('Hello World from LEMP Stack');
    
  9. Verify that the record exists.

    sql
    mysql> SELECT * FROM messages;
    

    Your output should be similar to the one below:

    +----+-----------------------------+
    | id | content                     |
    +----+-----------------------------+
    |  1 | Hello World from LEMP Stack |
    +----+-----------------------------+
    1 row in set (0.00 sec)
  10. Exit the MySQL console.

    sql
    mysql> EXIT;
    
  11. Create a PHP test file in the web root directory.

    console
    $ sudo nano /var/www/html/test.php
    
  12. Add the following PHP code to the file. Replace strong_password with the example_user password you set earlier.

    php
    <?php
    $servername = "localhost";
    $username = "example_user";
    $password = "strong_password";
    $dbname = "example_db";
    
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    if ($conn->connect_error) {
        die("Database connection failed: " . $conn->connect_error);
    }
    
    $sql = "SELECT content FROM messages";
    $result = $conn->query($sql);
    
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        echo "<h1>" . $row["content"] . "</h1>";
    } else {
        echo "<h1>No records found.</h1>";
    }
    
    $conn->close();
    ?>
    

    Save and close the file.

    This script connects to the example_db database, queries the messages table, and displays the result as an HTML heading.

  13. Access the test page in a web browser. Replace app.example.com with your actual domain name.

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

    The browser displays the message Hello World from LEMP Stack, confirming that Nginx, MySQL, and PHP are working together.

Conclusion

You have deployed and secured the LEMP stack on an Ubuntu 26.04 server. Nginx serves web requests, PHP-FPM processes dynamic content, and MySQL manages the application data. This stack supports multiple virtual hosts and integrates with frameworks such as Laravel and WordPress. For more configuration options, refer to the following resources:

Comments