How to Install Nginx, MySQL, PHP (LEMP Stack) on Rocky Linux 9

Updated on July 25, 2024
How to Install Nginx, MySQL, PHP (LEMP Stack) on Rocky Linux 9 header image

Introduction

Linux, Nginx, MySQL, and PHP (LEMP stack) is a collection of open-source applications that enable the development and hosting of dynamic web applications on a server. The stack includes Linux as the operating system, Nginx as the web server application, MySQL (or MariaDB) as the database backend, and PHP (or Python/Perl) as the server-side scripting language. The applications connect to each other using server modules to offer a powerful, efficient, and scalable environment for web development that allows developers to create, manage, and deliver high-performance web applications.

This article explains how to install the LEMP stack on Rocky Linux 9 and to deliver dynamic web applications on a server.

Prerequisites

Before you begin:

Install Nginx

Nginx is available in the default repositories on Rocky Linux 9. Follow the steps below to install the Nginx web server package using the default DNF package manager.

  1. Install Nginx.

    console
    $ sudo dnf install nginx
    
  2. View the installed Nginx version on your server.

    console
    $ nginx -v
    

    Output:

    nginx version: nginx/1.20.1
  3. Enable the Nginx service to start at boot time.

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

    console
    $ sudo systemctl start nginx
    
  5. View the Nginx service status and verify that it's running on your server.

    console
    $ sudo systemctl status nginx
    

    Output:

    ● nginx.service - The nginx HTTP and reverse proxy server
        Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled)
       Drop-In: /usr/lib/systemd/system/nginx.service.d
                └─php-fpm.conf
        Active: active (running) since Sat 2024-06-29 08:31:08 UTC; 3h 7min ago
        Process: 57241 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
        Process: 57242 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
        Process: 57243 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
       Main PID: 57244 (nginx)
          Tasks: 2 (limit: 11073)
         Memory: 2.1M
            CPU: 24ms
         CGroup: /system.slice/nginx.service
                 ├─57244 "nginx: master process /usr/sbin/nginx"
                 └─57245 "nginx: worker process"

Install MySQL

MySQL is available in the default Rocky Linux 9 repositories with the latest package information. You can switch between the MySQL package and MariaDB to use a database server depending on your development needs. In the following steps, install the MySQL database server package and configure the application to enable secure authentication for all database users.

  1. Install the latest MySQL database server package.

    console
    $ sudo dnf install mysql-server
    
  2. View the installed MySQL version on your server.

    console
    $ mysql --version
    

    Output:

    mysql  Ver 8.0.36 for Linux on x86_64 (Source distribution)
  3. Enable the MySQL service to automatically start at boot.

    console
    $ sudo systemctl enable mysqld
    

    Output:

    Created symlink /etc/systemd/system/multi-user.target.wants/mysqld.service → /usr/lib/systemd/system/mysqld.service.
  4. Start the MySQL service.

    console
    $ sudo systemctl start mysqld
    
  5. View the MySQL service status and verify that it's running on the server.

    console
    $ sudo systemctl status mysqld
    

    Output:

    ● mysqld.service - Mysql 8.0 database server
         Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled; preset: disabled)
         Active: active (running) since Sat 2024-06-29 08:09:41 UTC; 3h 28min ago
       Main PID: 56590 (mysqld)
         Status: "Server is operational"
          Tasks: 38 (limit: 11073)
         Memory: 488.5M
            CPU: 30.329s
         CGroup: /system.slice/mysqld.service
                 └─56590 /usr/libexec/mysqld --basedir=/usr
  6. Run the mysql_secure_installation script to enable authentication and disable insecure defaults on your MySQL database server.

    console
    $ sudo mysql_secure_installation
    
    • Enter Y when prompted to enable the VALIDATE PASSWORD component that ensures strict password policies for all database users.
    VALIDATE PASSWORD COMPONENT can be used to test passwords
    and improve security. It checks the strength of password
    and allows the users to set only those passwords which are
    secure enough. Would you like to setup VALIDATE PASSWORD component?
    
    Press y|Y for Yes, any other key for No: Y
    • Enter your desired password strength validation policy level. For example, enter 2 to enforce strong password usage on the server.
    LOW    Length >= 8
    MEDIUM Length >= 8, numeric, mixed case, and special characters
    STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file
    
    Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2
    • Enter Y and press Enter when prompted to remove anonymous users from the database server.
    Remove anonymous users? (Press y|Y for Yes, any other key for No) : 
    • Enter Y when prompted to disallow remote login access to the root database user.
    Disallow root login remotely? (Press y|Y for Yes, any other key for No) : 
    • Enter Y when prompted to remove the test database on your server.
    `Remove test database and access to it? (Press y|Y for Yes, any other key for No) : 
    • Enter Y and press Enter when prompted to reload and refresh the MySQL privilege tables to apply your configuration changes.
    Reload privilege tables now? (Press y|Y for Yes, any other key for No) : 

    Output:

    Success.
    
    All done! 
  7. Log in to the MySQL database server as the root user. Enter the root database user password you set earlier when prompted to access the MySQL console.

    console
    $ mysql -u root -p
    
  8. View all available databases on the server.

    sql
    mysql> show databases;
    

    Output:

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    +--------------------+
    4 rows in set (0.00 sec)
  9. Exit the MySQL console..

    sql
    mysql> exit;
    

Install PHP and Configure PHP-FPM

PHP processes the dynamic web content in your applications while PHP-FPM (FastCGI Process Manager) enables access to PHP with specific performance configurations on your server. Follow the steps below to install PHP and configure PHP-FPM to connect with the Nginx web server.

  1. Install PHP and PHP-FPM on your server.

    console
    $ sudo dnf install php php-fpm
    
  2. Install common PHP extensions required by most web applications.

    console
    $ sudo dnf install php-mysqlnd php-gd php-mbstring php-xml
    

    The above command installs the following extensions:

    • php-mysqlnd: Enables PHP to connect to the MySQL database server and perform SQL operations.
    • php-mbstring: Enables multi-byte string functions in PHP applications.
    • php-xml: Enables XML functionalities.
    • php-gd: Enables image manipulation functions in PHP applications.
  3. View the installed PHP version on your server.

    console
    $ php -v
    

    Output:

    PHP 8.0.30 (cli) (built: Aug  3 2023 17:13:08) ( NTS gcc x86_64 )
    Copyright (c) The PHP Group
    Zend Engine v4.0.30, Copyright (c) Zend Technologies
        with Zend OPcache v8.0.30, Copyright (c), by Zend Technologies
  4. Enable the PHP-FPM service to start at boot time.

    console
    $ sudo systemctl enable php-fpm
    

    Output:

    Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service.
  5. Start the PHP-FPM service.

    console
    $ sudo systemctl start php-fpm
    
  6. Open the default PHP-FPM pool www.conf to enable connections to the Nginx web server.

    console
    $ sudo nano /etc/php-fpm.d/www.conf
    
  7. Find the following user and group directives. Then, change the default values from apache to nginx.

    ini
    user = nginx
    group = nginx
    

    Save and close the file.

  8. Restart the PHP-FPM service to apply your configuration changes.

    console
    $ sudo systemctl restart php-fpm
    

Configure Nginx with PHP-FPM

Nginx connects to the PHP-FPM service using the socket path or the default TCP port 9000 on your server. In addition, Nginx must use the same user and group with PHP-FPM to allow PHP connections on the server. Follow the steps below to configure Nginx with PHP-FPM and enable the processing of PHP scripts on your server.

  1. Create a new info.php file in your default web root directory /var/www/html.

    console
    $ sudo nano /var/www/html/info.php
    
  2. Add the following contents to the file.

    php
    <?php
    
    phpinfo();
    
    ?>
    

    Save and close the file.

    The above PHP application code outputs information about the active PHP version information and modules available on your server.

  3. Create a new Nginx virtual host configuration file such as app.example.com.conf in the /etc/nginx/conf.d directory.

    console
    $ sudo nano /etc/nginx/conf.d/app.example.com.conf
    
  4. Add the following configurations to the file. Replace app.example.com with your actual domain name.

    nginx
    server {
        listen 80;
        server_name app.example.com;
    
        root /var/www/html; 
        index info.php;
    
        location / {
            try_files $uri $uri/ =404;
        }
    
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/run/php-fpm/www.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    
    # Deny access to the .htaccess file
    
        location ~ /\.ht {
            deny all;
        }
    }
    

    Save and close the file.

    The above Nginx server block configuration creates a new virtual host that listens for incoming connections on the HTTP port 80 using your domain app.example.com. Then, the web server delivers files using the index info.php from the default web root directory /var/www/html. The location ~ \.php block includes proxy directives that connect to the PHP-FPM Unix socket /run/php-fpm/www.sock to process all PHP file requests on your server.

  5. Test the Nginx configuration for errors.

    console
    $ 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
  6. Restart Nginx to apply your new configuration.

    console
    $ sudo systemctl restart nginx
    
  7. Grant the Nginx user and group nginx ownership privileges to the web root directory.

    console
    $ sudo chown -R nginx:nginx /var/www/html/
    
  8. Set the info.php file permissions to 755 to grant the nginx user full privileges. Then, assign read, and execute permissions to other users.

    console
    $ sudo chmod 755 /var/www/html/info.php
    
  9. Set the web root directory SELinux (Security-Enhanced Linux) context to httpd_sys_content_t to allow the Nginx web server to deliver files from the directory.

    console
    $ sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
    
  10. Restore the SELinux security context based on the httpd_sys_content_t policy rules to apply changes.

    console
    $ sudo restorecon -Rv /var/www/html
    
  11. View the web root directory context and verify that the web server policy httpd_sys_content_t is available.

    console
    $ ls -Z /var/www/html
    

    Output:

    unconfined_u:object_r:httpd_sys_content_t:s0 info.php 
  12. Allow HTTP connections through the default firewall.

    console
    $ sudo firewall-cmd --zone=public --permanent --add-service=http
    
  13. Reload the firewall to apply the configuration changes.

    console
    $ sudo firewall-cmd --reload
    
  14. Access your domain using a web browser such as Chrome and verify that your PHP application information displays.

    http://app.example.com

    Test LEMP installation

Test the Installation

Nginx handles HTTP requests and forwards them to PHP-FPM for processing. In addition, the php-mysqlnd module interacts with the MySQL database to retrieve or store data on the server. Then, PHP-FPM processes the dynamic content and to response to the Nginx user request. Follow the steps below to create a new sample PHP application that displays a Greetings from Vultr message from a MySQL database on your server.

  1. Log in to the MySQL database server as the root user.

    console
    $ mysql -u root -p
    
  2. Create a new sample database test_db.

    sql
    mysql> CREATE DATABASE test_db;
    
  3. Switch to the test_db database.

    sql
    mysql> USE test_db;
    
  4. Create a new database user. For example, test_user with a strong password. Replace Strong)P@ssword123 with your desired password.

    sql
    mysql> CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'Strong)P@ssword123';
    
  5. Grant the new test_user full privileges to the test_db database.

    sql
    mysql> GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost';
    
  6. Reload the MySQL privileges table to apply changes.

    sql
    mysql> FLUSH PRIVILEGES;
    
  7. Switch to the test_db database.

    sql
    mysql> USE test_db;
    
  8. Create a new sample table greetings with two columns: id to store numeric data and message for mixed-characters.

    sql
    mysql> CREATE TABLE greetings (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255) NOT NULL);
    
  9. Insert a new Greetings from Vultr string to the message table column.

    sql
    mysql> INSERT INTO greetings (message) VALUES ('Greetings from Vultr');
    
  10. Query all available table data to verify that the new Greetings from Vultr string is available.

    sql
    mysql> SELECT * FROM greetings;
    

    Output:

    +----+----------------------+
    | id | message              |
    +----+----------------------+
    |  1 | Greetings from Vultr |
    +----+----------------------+
  11. Exit the MySQL console.

    sql
    mysql> exit;
    
  12. Create a new PHP application file webapp.php in your /var/www/html/ web root directory.

    console
    $ sudo nano /var/www/html/webapp.php
    
  13. Add the following contents to the file.

    php
    <?php
    $servername = "localhost";
    $username = "test_user";
    $password = "Strong)P@ssword123";
    $dbname = "test_db";
    
    // Create database connection
    $conn = new mysqli($servername, $username, $password, $dbname);
    
    // Check database connection
    if ($conn->connect_error) {
        die("Database Connection Failed." . $conn->connect_error);
    }
    
    echo "<h4 align='center'> Below is the message retrieved from the test_db Mysql database on your server</h4>";
    
    // Retrieve the record from greetings Table
    $sql = "SELECT message FROM greetings";
    $result = $conn->query($sql);
    
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        echo "<h1 align='center'>" . $row["message"]. "</h1>";
    
    } else {
        echo "<h1 align='center'>No message found.</h1>";
    }
    
    $conn->close();
    ?>
    

    Save and close the file.

    The above PHP application code connects to the MySQL database server and retrieves the message Greetings from Vultr from the greetings table. Then, it displays the result in your web browser. The application displays a No message found prompt in your browser when the database table is empty.

  14. Enable the httpd_sys_content_t SELinux context on the new PHP application file.

    console
    $ sudo restorecon -v /var/www/html/webapp.php
    
  15. Access your domain and load the /webapp.php URL path in your web browser to test the PHP application.

    http://app.example.com/webapp.php

    Test the LEMP stack

Conclusion

You have installed Nginx, MySQL, and PHP (LEMP stack) on your Rocky Linux 9 server. You can use the LEMP stack to develop, host, and securely deliver dynamic web applications on your server. For more information and configuration options, visit the following official documentation resources: