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:
| Package | Purpose |
|---|---|
php-fpm | FastCGI Process Manager – required for Nginx and recommended for Apache |
php-cli | Command-line interface for running PHP scripts |
php-mysqlnd | Native MySQL/MariaDB driver |
php-pgsql | PostgreSQL database driver |
php-curl | Client URL library for HTTP requests |
php-gd | Image processing library |
php-mbstring | Multibyte string handling |
php-xml | XML parsing and manipulation |
php-zip | ZIP archive handling |
php-intl | Internationalization functions |
php-opcache | Opcode caching for performance |
php-redis | Redis 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.






























































Excellent article! Went without a hitch… thanks!
Awesome welcome.
Good work, thanks
Welcome.