PHP is a recursive acronym that stands for PHP: Hypertext Preprocessor. It is a popular general-purpose scripting language used in web development and can be embedded in HTML. It is a fast, unique, flexible, and pragmatic language that powers from simple blog sites to popular websites. PHP is mainly used in server-side scripting where you use a PHP parser (CGI or server module) to collect form data, generate dynamic page content, or send and receive cookies. But PHP can do much more like command line scripting that allows you to run a PHP script without any server or browser and write desktop applications with a graphical interface including cross-platform applications.
PHP can be used in all major operating systems including Windows, macOS, and Linux. It supports web servers to work either as a module or a CGI processor, this includes servers like Apache, IIS, Lighttpd, and Nginx. PHP includes different abilities like outputting images, PDF files, and any text, such as XHTML and any other XML file. PHP has useful text-processing features like Perl-compatible regular expressions that parse and access XML documents. It also supports a wide range of databases while writing to the database is simple with the use of specific extensions like MySQL, using an abstraction layer like PDO, or Open Database Connection standard via the ODBC extension.
PHP 8.5 is the newest branch, but 8.4 still gets security releases, and its October 2026 release carries the fix for the PHP2Shell remote code execution bugs. This guide installs PHP 8.4 on Rocky Linux 9 / AlmaLinux 9 from Remi’s modular repository, serves it through Apache or Nginx with PHP-FPM, and shows you how to prove the installed build is patched. Rocky Linux 9.8 ran the full Apache and Nginx paths below in October 2026 with Remi’s PHP 8.4.27, and AlmaLinux 9.8 ran the 8.4.26 to 8.4.27 upgrade. SELinux and reboots were not part of that test.
Install PHP 8.4 on Rocky Linux 9 / AlmaLinux 9
Enable the CRB, EPEL and Remi repositories in Rocky Linux 9 and AlmaLinux 9. Remi’s packages need libraries from EPEL, and EPEL needs CRB. The config-manager subcommand comes from dnf-plugins-core, which a minimal install may not have: on our minimal Rocky Linux 9 box it failed with No such command: config-manager until that package went in, so the first line installs it.
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf install epel-release -y
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf update -y
Once done, list the available PHP streams:
sudo dnf module list php
AppStream offers the 8.1, 8.2 and 8.3 streams, and Remi’s modular repository adds every branch from 7.4 up, including remi-8.4:
Rocky Linux 9 - AppStream
Name Stream Profiles Summary
php 8.1 common [d], devel, minimal PHP scripting language
php 8.2 common [d], devel, minimal PHP scripting language
php 8.3 common [d], devel, minimal PHP scripting language
Remi's Modular repository for Enterprise Linux 9 - x86_64
Name Stream Profiles Summary
php remi-7.4 common [d], devel, minimal PHP scripting language
php remi-8.0 common [d], devel, minimal PHP scripting language
php remi-8.1 common [d], devel, minimal PHP scripting language
php remi-8.2 common [d], devel, minimal PHP scripting language
php remi-8.3 common [d], devel, minimal PHP scripting language
php remi-8.4 common [d], devel, minimal PHP scripting language
php remi-8.5 common [d], devel, minimal PHP scripting language
php remi-8.6 common [d], devel, minimal PHP scripting language
Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
Enable the module before installing PHP 8.4.
sudo dnf module enable php:remi-8.4 -y
With the stream enabled, every php* package you install comes from Remi’s 8.4 branch. Pick Apache or Nginx below, not both, because each one wants port 80.
Using PHP 8.4 with Apache Web server
Install the Apache web server.
sudo dnf install httpd httpd-tools -y
Start and enable the service.
sudo systemctl start httpd
sudo systemctl enable httpd
To install PHP for Apache run the following command.
sudo dnf install php php-cli php-common php-fpm
sudo systemctl enable --now php-fpm
Restart Apache now. The PHP package drops /etc/httpd/conf.d/php.conf, which hands .php files to PHP-FPM, but Apache only reads it on a restart. Because Apache was already running, our test page came back as plain PHP source with HTTP 200 until we restarted it, which leaks code on a real site.
sudo systemctl restart httpd
Create a PHP test page using the following command.
sudo vim /var/www/html/info.php
Add the following code and save the file.
<?php
phpinfo();
?>
Apache users can skip the Nginx section and go straight to the verification step.
Using PHP 8.4 with Nginx Web server
Install Nginx with the following command.
sudo dnf install nginx vim -y
Start and enable the service to start on boot.
sudo systemctl start nginx
sudo systemctl enable nginx
Install PHP on the Nginx web server by running the following command.
sudo dnf install php php-cli php-common php-fpm
The php-fpm package already wires itself into Nginx, so you don’t edit nginx.conf. It ships /etc/nginx/conf.d/php-fpm.conf, an upstream pointing at the FPM socket, and /etc/nginx/default.d/php.conf, which the default server block includes. Older versions of this guide pasted a location block with fastcgi_pass 127.0.0.1:9000, but Remi’s PHP-FPM listens on a Unix socket, so nothing answers on port 9000. Confirm where Nginx sends PHP requests.
sudo nginx -T 2>/dev/null | grep -E 'server unix|fastcgi_pass'
Both lines point at the PHP-FPM socket through the php-fpm upstream:
server unix:/run/php-fpm/www.sock;
fastcgi_pass php-fpm;
The shipped php.conf also has try_files $uri =404;, so Nginx returns 404 for a .php file that does not exist instead of passing it to PHP-FPM. Setting cgi.fix_pathinfo to 0 in PHP adds a second guard. In Remi’s /etc/php.ini the line ships commented out as ;cgi.fix_pathinfo=1, so uncomment it and set it to 0 in one step:
sudo sed -i 's/^;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/' /etc/php.ini
Run grep '^cgi.fix_pathinfo' /etc/php.ini afterwards and you should see cgi.fix_pathinfo=0. If it prints nothing, the line was already edited, so open the file with sudo vim /etc/php.ini and set it by hand.
Test the configuration syntax.
sudo nginx -t
Both lines should report success before you go on.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Start and enable PHP-FPM service:
sudo systemctl enable --now php-fpm
Reload Nginx so it picks up the PHP configuration that arrived after it started. The reload takes a moment: a request sent in the same second came back as the raw file in our test, and the page rendered normally two seconds later.
sudo systemctl reload nginx
Create a test file.
sudo vim /usr/share/nginx/html/info.php
Add the following lines and save the file.
<?php
phpinfo();
?>
Nginx serves that file from its default document root, so you can test it right away.
Verify PHP installation
If you have Firewalld service running open http port.
sudo firewall-cmd --add-service={http,https} --permanent
sudo firewall-cmd --reload
Check for the PHP version after the installation.
php -v
You should see 8.4.27 or newer, and Remi’s build identifies itself in the third line.
PHP 8.4.27 (cli) (built: Oct 19 2026 14:38:59) (NTS gcc x86_64)
Copyright (c) The PHP Group
Built by Remi's RPM repository <https://rpms.remirepo.net/> #StandWithUkraine #NoAI
Zend Engine v4.4.27, Copyright (c) Zend Technologies
with Zend OPcache v8.4.27, Copyright (c), by Zend Technologies
Go to the Web browser at http://localhost/info.php to get the following screen. The page reports Server API: FPM/FastCGI on both web servers. The screenshot was captured in December 2024 on PHP 8.4.2, so your page shows a newer version.

Delete info.php once you have seen the page, because it tells anyone who finds it your exact PHP build and configuration.
Confirm the PHP2Shell fix (CVE-2026-109618 and CVE-2026-109619)
PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two remote code execution bugs in PHP itself, rated CVSS v4.0 9.2 in PHP’s 20 October pre-announcement and fixed on 21 October 2026 in 8.5.12, 8.4.27, 8.3.36 and 8.2.35 (see the PHP security advisory). Remi’s remi-8.4 stream now ships 8.4.27, so a fresh install from this guide is patched. That was not true on day one: php.net’s 21 October advisory told Remi users to switch to distro packages because Remi had no update yet, and Remi published the fixed builds by 22 October. Remi’s changelog says “Update to 8.4.27” without the CVE IDs, so the package version is the check.
rpm -q php-common
Version 8.4.27 or newer is fixed, and a fresh install can stop here.
php-common-8.4.27-1.module_php.8.4.el9.remi.x86_64
On an existing server that still shows 8.4.26 or older, upgrade every PHP package and restart PHP-FPM yourself. php-fpm restarted itself during the transaction in our AlmaLinux 9 test, so restart once more and confirm the timestamp. Apache and Nginx hand PHP to FPM in this setup and need no restart, but long-running PHP CLI workers (queue workers, supervisor jobs) do:
sudo dnf upgrade -y "php*"
sudo systemctl restart php-fpm
systemctl show -p ActiveEnterTimestamp php-fpm
Our AlmaLinux 9 box went from 8.4.26 to 8.4.27 at 19:33, and the start time must be later than the upgrade, which sudo dnf history lists at the top. Ours read as follows.
ActiveEnterTimestamp=Thu 2026-10-22 19:33:33 UTC
If dnf finds nothing to upgrade but the version is still old, your mirror may lag: run sudo dnf clean metadata and retry later. If you would rather stay on Red Hat’s packages, the AppStream php:8.3 stream (8.3.36) and php:8.2 stream (8.2.35) were both fixed on our Rocky Linux 9 box, while php:8.1 still served unpatched 8.1.32. AlmaLinux 9.8 is ahead there: its php:8.1 build 8.1.32 with the .alma.1 suffix carries an AlmaLinux backport that names both CVEs in its changelog, and its php:8.2 (8.2.35) and php:8.3 (8.3.36) streams are fixed too. Switching from Remi moves your application from PHP 8.4 to 8.3, so check its PHP requirements first. On Rocky Linux 9 the switch took the commands below. Without -y, dnf shows the transaction and waits, so review it before you answer: --allowerasing removes every Remi-only extension AppStream has no build for (php-sodium in our test, and php-pecl-* packages such as redis or imagick on a typical app server).
sudo dnf module reset php -y
sudo dnf module enable php:8.3 -y
sudo dnf distro-sync --allowerasing "php*"
sudo systemctl restart php-fpm
Afterwards rpm -q php-common returned php-common-8.3.36-1.module+el9.8.0+40396+4e680bb7.x86_64 and the test page reported 8.3.36 through FPM. For other distributions and repositories, our PHP2Shell check and patch guide lists the fixed package for each.
Wrap Up
PHP is a popular general-purpose programming language that is used in web development to produce dynamic web content. It contains a lot of features that make it a fast and flexible scripting language including the main one that it can be embedded into HTML. Others include using PHP from the command line, support of cookies and sessions, handling file uploads, using remote files, and enabling HTTP authentication.
Check out more articles: