A LEMP stack — Linux, Nginx, MySQL (or MariaDB), and PHP — is one of the most common foundations for hosting WordPress, Laravel, and other PHP applications. On RHEL 8, each component is available from the default AppStream repository using module streams, giving you fine-grained control over which PHP version you install without relying on third-party repositories. This tutorial walks through installing and configuring all four components, connecting Nginx to PHP-FPM via a Unix socket, and verifying the stack with a phpinfo() page. SELinux contexts and firewalld rules are included at every stage so the stack works correctly in RHEL 8’s default enforcing environment.

Prerequisites

  • RHEL 8 server with a sudo-capable user
  • Active RHEL subscription or CentOS/Rocky Linux 8 equivalent
  • Ports 80 and 443 available
  • firewalld active and running
  • SELinux in enforcing mode

Step 1 — Install and Start Nginx

Install Nginx from the AppStream and enable it as a persistent service.

sudo dnf install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

curl -s http://localhost | grep -i nginx

Step 2 — Install and Secure MySQL (or MariaDB)

RHEL 8 AppStream provides both MySQL 8.0 and MariaDB 10.3 module streams. This example uses MySQL 8.0. Run the secure installation script to set a root password and remove test accounts.

# Enable the MySQL 8.0 module stream
sudo dnf module enable -y mysql:8.0
sudo dnf install -y mysql-server

sudo systemctl enable mysqld
sudo systemctl start mysqld
sudo systemctl status mysqld

# Secure the installation
sudo mysql_secure_installation
# Follow prompts: set root password, remove anonymous users,
# disallow remote root login, remove test database

# Verify login
sudo mysql -u root -p -e "SHOW DATABASES;"

For MariaDB instead, substitute mysql:8.0 with mariadb:10.5 and the package name with mariadb-server.

Step 3 — Install PHP 8.0 via the AppStream Module

RHEL 8 AppStream ships PHP as a module stream. Select the 8.0 stream and install the common profile, which includes PHP-FPM and the most frequently needed extensions.

sudo dnf module reset php
sudo dnf module enable -y php:8.0
sudo dnf module install -y php:8.0/common

# Install additional extensions for WordPress / general PHP apps
sudo dnf install -y php-mysqlnd php-gd php-xml php-mbstring 
    php-opcache php-json php-curl php-zip

php -v
sudo systemctl enable php-fpm
sudo systemctl start php-fpm
sudo systemctl status php-fpm

Step 4 — Configure Nginx to Pass PHP Requests to PHP-FPM

PHP-FPM by default listens on a Unix socket at /run/php-fpm/www.sock. Create a server block for your site that passes .php requests to that socket.

sudo mkdir -p /var/www/example.com/html
sudo chown -R nginx:nginx /var/www/example.com

sudo tee /etc/nginx/conf.d/example.com.conf <<'EOF'
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com/html;
    index index.php index.html;

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

    location ~ .php$ {
        fastcgi_pass   unix:/run/php-fpm/www.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    location ~ /.ht {
        deny all;
    }
}
EOF

sudo nginx -t && sudo systemctl reload nginx

Step 5 — Apply SELinux Contexts to the Web Root

On RHEL 8 with SELinux enforcing, the web root must carry the httpd_sys_content_t context so Nginx and PHP-FPM can read files. Directories where PHP writes (uploads, cache) need the writable variant httpd_sys_rw_content_t.

sudo semanage fcontext -a -t httpd_sys_content_t 
    "/var/www/example.com(/.*)?"
sudo restorecon -Rv /var/www/example.com

# Allow Nginx to connect to PHP-FPM socket
sudo setsebool -P httpd_can_network_connect on

# If using MySQL over the network
sudo setsebool -P httpd_can_network_connect_db on

# Verify contexts
ls -lZ /var/www/example.com/html/

Step 6 — Create a phpinfo() Test Page and Verify the Stack

Drop a PHP info page into the document root, verify it renders through Nginx and PHP-FPM, then remove it before going to production.

sudo tee /var/www/example.com/html/info.php <<'EOF'

EOF
sudo chown nginx:nginx /var/www/example.com/html/info.php

# Restore SELinux context on the new file
sudo restorecon /var/www/example.com/html/info.php

curl -s http://localhost/info.php | grep -E "PHP Version|mysql|opcache"

# Remove the info page when done — it exposes server internals
sudo rm /var/www/example.com/html/info.php

Conclusion

You now have a fully functional LEMP stack running on RHEL 8 with Nginx serving static files, PHP-FPM handling PHP execution via a Unix socket, and MySQL 8.0 storing application data. The AppStream module system means you can switch PHP versions with a single dnf module switch-to command and a service restart, without adding third-party repositories. SELinux file contexts and the httpd_can_network_connect boolean keep the stack secure by default. To install WordPress on top of this stack, create a database and user in MySQL, download the WordPress archive to the document root, and run through the web-based installer.

Next steps: How to Configure Nginx FastCGI Caching on RHEL 8, How to Set Up Varnish Cache as a Reverse Proxy on RHEL 8, and How to Install and Configure OpenLiteSpeed Web Server on RHEL 8.