This guide walks you through installing PHP 8.4 on RHEL 10, Rocky Linux 10, and AlmaLinux 10. PHP 8.4 brings property hooks, asymmetric visibility, the new array_find() function, improved JIT performance, and deprecation of implicit nullable parameter types. We will cover installation from both the default AppStream module and the Remi repository, along with configuration for Nginx and Apache.

At the time of writing, RHEL 10 and its derivatives ship PHP 8.3 in the default AppStream repository. To get PHP 8.4, you need the Remi repository. This guide covers both methods so you can pick the one that fits your environment.

Prerequisites

Before you begin, make sure the following are in place:

  • A running instance of RHEL 10, Rocky Linux 10, or AlmaLinux 10 with root or sudo access.
  • System packages updated to the latest versions.
  • A working internet connection for downloading packages.

Start by updating your system:

sudo dnf update -y

Step 1: Enable EPEL and Remi Repositories

The EPEL (Extra Packages for Enterprise Linux) repository is a dependency for Remi, which provides the latest PHP releases packaged for RHEL-based distributions.

Install EPEL repository

sudo dnf install -y epel-release

On RHEL 10 (not Rocky or Alma), you may need to enable CodeReady Builder first:

sudo subscription-manager repos --enable codeready-builder-for-rhel-10-x86_64-rpms
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm

Install Remi repository

sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-10.rpm

Verify both repositories are enabled:

sudo dnf repolist | grep -E 'epel|remi'

You should see entries for both epel and remi in the output.

Step 2: Reset and Enable the PHP 8.4 Module

RHEL 10 uses DNF modularity to manage PHP versions. If a PHP module is already active, you need to reset it before switching to Remi’s PHP 8.4 stream.

sudo dnf module list php

Reset the current PHP module stream:

sudo dnf module reset php -y

Now enable the Remi PHP 8.4 module stream:

sudo dnf module enable php:remi-8.4 -y

Confirm the active stream:

sudo dnf module list php

The output should show remi-8.4 [e] indicating the stream is enabled.

Step 3: Install PHP 8.4 and Extensions

Install PHP 8.4 along with the most commonly needed extensions:

sudo dnf install -y php php-fpm php-cli php-mysqlnd php-pgsql php-curl php-gd php-mbstring php-xml php-zip php-intl php-opcache php-redis

Here is what each extension does:

PackagePurpose
php-fpmFastCGI Process Manager – required for Nginx and recommended for Apache
php-cliCommand-line interface for running PHP scripts
php-mysqlndNative MySQL/MariaDB driver
php-pgsqlPostgreSQL database driver
php-curlClient URL library for HTTP requests
php-gdImage processing library
php-mbstringMultibyte string handling
php-xmlXML parsing and manipulation
php-zipZIP archive handling
php-intlInternationalization functions
php-opcacheOpcode caching for performance
php-redisRedis key-value store driver

Step 4: Verify the PHP Installation

Check the installed PHP version:

php -v

Expected output:

PHP 8.4.x (cli) (built: ...)
Copyright (c) The PHP Group
Zend Engine v4.4.x, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.x, Copyright (c), by Zend Technologies

List all loaded PHP modules to confirm your extensions are active:

php -m

Step 5: Configure php.ini

The main PHP configuration file is located at /etc/php.ini. Open it with your preferred editor:

sudo vi /etc/php.ini

Below are the settings I recommend adjusting for most production workloads. Change the values to match your server resources and application requirements.

Memory and execution limits

memory_limit = 256M
max_execution_time = 300
max_input_time = 300
max_input_vars = 5000

File upload settings

upload_max_filesize = 64M
post_max_size = 64M

OPcache settings

OPcache dramatically improves PHP performance by caching precompiled bytecode in shared memory. Add or update these directives in /etc/php.d/10-opcache.ini:

sudo vi /etc/php.d/10-opcache.ini

Set the following values:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.validate_timestamps=1
opcache.save_comments=1
opcache.jit=on
opcache.jit_buffer_size=128M

The JIT compiler in PHP 8.4 provides additional performance gains for CPU-bound workloads. The opcache.jit=on setting enables it with the default tracing mode.

Step 6: Configure PHP-FPM

PHP-FPM handles PHP requests as a separate process pool and is the recommended way to run PHP with both Nginx and Apache. The main pool configuration file is:

sudo vi /etc/php-fpm.d/www.conf

Key settings to review and adjust:

; Process user and group - match your web server user
user = nginx
group = nginx

; Listen on a Unix socket for better performance
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

; Process manager settings
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

If you are using Apache instead of Nginx, change the user, group, listen.owner, and listen.group values to apache:

user = apache
group = apache
listen.owner = apache
listen.group = apache

A quick note on the pm directive:

  • dynamic – spawns child processes on demand between min and max limits (good default for most servers).
  • static – keeps a fixed number of child processes running at all times (useful for dedicated PHP servers with predictable load).
  • ondemand – only spawns workers when requests arrive, then kills idle ones (good for low-traffic sites to save memory).

Step 7: Enable and Start PHP-FPM

sudo systemctl enable --now php-fpm

Verify PHP-FPM is running:

sudo systemctl status php-fpm

You should see active (running) in the output. Also confirm the socket file exists:

ls -la /run/php-fpm/www.sock

Step 8: Integrate PHP 8.4 with Nginx

If you are running Nginx, install it first if you have not already:

sudo dnf install -y nginx
sudo systemctl enable --now nginx

Create or edit your Nginx server block to pass PHP requests to PHP-FPM. Here is an example configuration:

sudo vi /etc/nginx/conf.d/default.conf
server {
    listen 80;
    server_name your_domain.com;
    root /var/www/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;
    }
}

Test the Nginx configuration and reload:

sudo nginx -t && sudo systemctl reload nginx

Step 9: Integrate PHP 8.4 with Apache

Apache supports PHP through two methods: mod_php and PHP-FPM. PHP-FPM is the recommended approach because it handles processes independently and performs better under load.

Option A: Using PHP-FPM with Apache (Recommended)

Install Apache and the FastCGI proxy module:

sudo dnf install -y httpd
sudo systemctl enable --now httpd

Make sure the user/group in /etc/php-fpm.d/www.conf is set to apache as shown in Step 6. Then create a configuration file for PHP-FPM:

sudo vi /etc/httpd/conf.d/php-fpm.conf
<FilesMatch \.php$>
    SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>

DirectoryIndex index.php

Restart both services:

sudo systemctl restart php-fpm httpd

Option B: Using mod_php with Apache

If you prefer the traditional mod_php approach (simpler setup but less efficient), the PHP package installs the Apache module automatically. Just make sure the module is loaded:

sudo dnf install -y httpd php
sudo systemctl restart httpd

Verify the module is loaded:

httpd -M | grep php

You should see php_module in the output. Note that mod_php runs PHP inside the Apache process itself, which uses more memory per worker than PHP-FPM. For production servers handling significant traffic, PHP-FPM is the better choice.

Step 10: Test with phpinfo()

Create a test PHP file in your web root to verify everything is working:

echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php

Open your browser and navigate to:

http://your_server_ip/info.php

You should see the PHP information page showing version 8.4.x with all your installed extensions listed. Check the following sections:

  • PHP Version – confirms 8.4.x
  • Server API – shows FPM/FastCGI (if using PHP-FPM) or Apache 2.0 Handler (if using mod_php)
  • Loaded Configuration File – should point to /etc/php.ini
  • OPcache – should show enabled with JIT active

Important: Remove the test file after verification. Leaving phpinfo() exposed is a security risk as it reveals detailed server configuration.

sudo rm -f /var/www/html/info.php

Managing Multiple PHP Versions with DNF Modules

One of the advantages of using DNF module streams is the ability to switch between PHP versions without manually removing packages.

List available PHP module streams

sudo dnf module list php

This shows all available streams from both the AppStream and Remi repositories.

Switch to a different PHP version

To switch from PHP 8.4 to, say, PHP 8.3:

sudo dnf module reset php -y
sudo dnf module enable php:remi-8.3 -y
sudo dnf distro-sync -y

After switching, verify the active version:

php -v

Then restart PHP-FPM and your web server:

sudo systemctl restart php-fpm
sudo systemctl restart nginx   # or httpd for Apache

Switch back to PHP 8.4

sudo dnf module reset php -y
sudo dnf module enable php:remi-8.4 -y
sudo dnf distro-sync -y
sudo systemctl restart php-fpm

Troubleshooting

PHP-FPM fails to start

Check the PHP-FPM logs for errors:

sudo journalctl -u php-fpm -e --no-pager

Common causes:

  • Socket permission errors – verify listen.owner and listen.group in www.conf match your web server user.
  • Port already in use – another PHP-FPM instance or process may be binding to the same socket/port. Check with ss -tlnp | grep php.
  • Syntax errors in configuration – validate with php-fpm -t.

502 Bad Gateway in Nginx

This usually means Nginx cannot communicate with PHP-FPM. Check these:

# Confirm PHP-FPM is running
sudo systemctl status php-fpm

# Check the socket file exists and has correct permissions
ls -la /run/php-fpm/www.sock

# Verify Nginx is pointing to the correct socket path
grep fastcgi_pass /etc/nginx/conf.d/*.conf

PHP extensions not loading

If a specific extension does not show up in php -m output:

# Check if the extension package is installed
rpm -qa | grep php-

# Verify the .ini file exists in the scan directory
ls /etc/php.d/

# Check for errors when loading the extension
php -d display_errors=1 -r "phpinfo();" 2>&1 | grep -i error

Module stream conflicts

If you see errors about conflicting module streams when installing PHP:

# Reset all PHP module streams
sudo dnf module reset php -y

# Remove any existing PHP packages
sudo dnf remove -y 'php-*'

# Re-enable the desired stream and install
sudo dnf module enable php:remi-8.4 -y
sudo dnf install -y php php-fpm php-cli

SELinux blocking PHP-FPM

On RHEL-based systems, SELinux may block PHP-FPM from accessing certain files or connecting to databases. Check for denials:

sudo ausearch -m avc -ts recent

Common SELinux booleans you may need to enable:

# Allow PHP-FPM to connect to databases over the network
sudo setsebool -P httpd_can_network_connect_db 1

# Allow PHP-FPM to make outbound network connections
sudo setsebool -P httpd_can_network_connect 1

# Allow PHP-FPM to send emails
sudo setsebool -P httpd_can_sendmail 1

Firewall not allowing HTTP traffic

If you cannot reach your web server from a browser, open the necessary firewall ports:

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

Conclusion

You now have PHP 8.4 running on RHEL 10, Rocky Linux 10, or AlmaLinux 10. We covered installing PHP from the Remi repository using DNF module streams, configuring php.ini and PHP-FPM for production use, integrating with both Nginx and Apache, and switching between PHP versions. The Remi repository makes it straightforward to stay current with the latest PHP releases while DNF modules provide a clean way to manage version changes across your infrastructure.

4 COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here