Most CentOS Stream web stacks start with AppStream PHP packages because DNF keeps the runtime, extensions, and security updates tied to the system package set. You can install PHP on CentOS Stream 10 as PHP 8.3 directly, while CentOS Stream 9 uses module streams for PHP 8.1, 8.2, and 8.3.
Use the Apache path when HTTPD will serve PHP through the packaged PHP-FPM handler, or choose the Nginx PHP-FPM path when Nginx will pass requests to a FastCGI socket. The same package workflow covers CLI checks, common extensions, PHP-FPM service setup, updates, removal, and AppStream troubleshooting.
CentOS Stream 10 and CentOS Stream 9 are the supported releases here. Commands are separated only where package behavior differs between the two releases.
Install PHP on CentOS Stream
Start by matching your CentOS Stream release to the PHP branch and web-server integration you plan to use.
Choose a PHP Version on CentOS Stream
| CentOS Stream Release | Package Source | PHP Branches | What To Do |
|---|---|---|---|
| CentOS Stream 10 | AppStream packages | PHP 8.3 | Install PHP packages directly with DNF. |
| CentOS Stream 9 | AppStream module streams | PHP 8.1, 8.2, and 8.3 | Enable one PHP module stream before installing packages. |
PHP 8.3 is the best AppStream choice for new deployments unless an application requires PHP 8.2 or 8.1. For newer branches outside AppStream, keep that workflow separate and use the dedicated guide to install Remi RPM repository on CentOS Stream.
Update CentOS Stream Before Installing PHP
Refresh package metadata and apply pending system updates before adding PHP packages:
sudo dnf upgrade --refresh
Commands that start with
sudorequire an account with administrator privileges. If your user cannot runsudo, switch to a properly privileged account before continuing.
Install PHP 8.3 on CentOS Stream 10
CentOS Stream 10 provides PHP 8.3 as normal AppStream packages, so module commands are not needed.
Install PHP for Apache on CentOS Stream 10
Use the Apache package path when your site runs through HTTPD. The php package is a small AppStream metapackage that pulls PHP-FPM and the Apache PHP handler configuration, and it may also pull httpd if Apache is not already present. For the full web-server setup, use the separate guide to install Apache HTTPD on CentOS Stream.
sudo dnf install php php-cli
Test Apache’s configuration, start PHP-FPM, then restart HTTPD so Apache can pass PHP files to the default PHP-FPM socket:
sudo apachectl configtest
sudo systemctl enable --now php-fpm
sudo systemctl restart httpd
Install PHP-FPM for Nginx on CentOS Stream 10
Use PHP-FPM for Nginx. This installs the FastCGI service and the PHP command-line binary without installing the Apache PHP package:
sudo dnf install php-fpm php-cli
Install PHP on CentOS Stream 9 with AppStream Modules
CentOS Stream 9 exposes supported PHP branches through DNF module streams. Enable exactly one stream, then install the package set that matches your web server.
List PHP Module Streams on CentOS Stream 9
Check the current AppStream PHP branches before choosing one:
dnf module list php
Relevant output includes:
CentOS Stream 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, devel, minimal PHP scripting language Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
Enable a PHP Stream on CentOS Stream 9
For new deployments, enable PHP 8.3:
sudo dnf module enable php:8.3
For applications that still require PHP 8.2, enable that stream instead and skip the PHP 8.3 command:
sudo dnf module enable php:8.2
PHP 8.1 remains available for compatibility workloads with sudo dnf module enable php:8.1. Run only one module-enable command before installing packages.
Verify the enabled stream when you are unsure which branch DNF will use:
dnf module list php --enabled
For PHP 8.3, relevant output includes:
CentOS Stream 9 - AppStream Name Stream Profiles Summary php 8.3 [e] common, devel, minimal PHP scripting language
Install PHP for Apache on CentOS Stream 9
After enabling the stream, install the Apache-oriented PHP package set and CLI component:
sudo dnf install php php-cli
Test Apache’s configuration, start PHP-FPM, then restart HTTPD so Apache can use the PHP handler configuration installed with the package set:
sudo apachectl configtest
sudo systemctl enable --now php-fpm
sudo systemctl restart httpd
Install PHP-FPM for Nginx on CentOS Stream 9
For Nginx, install PHP-FPM and the CLI component from the enabled stream:
sudo dnf install php-fpm php-cli
Verify PHP on CentOS Stream
Check the active PHP branch after installation:
php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . PHP_EOL;'
A PHP 8.3 install returns:
8.3
Use php -v when you need the full patch version and build details.
Install Common PHP Extensions on CentOS Stream
Most CMS and framework deployments need database, XML, image, internationalization, cache, and archive extensions in addition to the base runtime. Install the common AppStream extension set with DNF:
sudo dnf install php-mysqlnd php-gd php-opcache php-intl php-bcmath php-xml php-mbstring php-pdo php-pecl-apcu php-pecl-zip
The package names track your selected source. On CentOS Stream 9, DNF installs these extensions from the enabled PHP module stream.
- php-mysqlnd: MySQL native driver support for database connections.
- php-gd: Image manipulation support for applications that generate thumbnails or process uploads.
- php-opcache: Bytecode caching for faster repeated PHP execution.
- php-intl: Locale, collation, and internationalization functions.
- php-bcmath: Arbitrary precision math used by some commerce and accounting applications.
- php-xml: XML parsing and DOM support.
- php-mbstring: Multi-byte string handling for UTF-8-heavy applications.
- php-pdo: Database abstraction support used by many frameworks.
- php-pecl-apcu: User cache support for storing application data in memory.
- php-pecl-zip: ZIP archive handling for uploads, backups, and import/export workflows.
Verify the installed modules with a focused module check:
php -m | grep -E '^(apcu|bcmath|gd|intl|mbstring|mysqli|mysqlnd|PDO|pdo_mysql|xml|Zend OPcache|zip)$' | LC_ALL=C sort -u
Relevant output includes:
PDO Zend OPcache apcu bcmath gd intl mbstring mysqli mysqlnd pdo_mysql xml zip
Install PHP Development Tools
Development servers that build extensions or use step debugging can add the development headers and Xdebug package:
sudo dnf install php-devel php-pecl-xdebug3
The development package pulls compiler and header dependencies. Keep it off production servers unless the application or deployment workflow needs those build tools.
Configure PHP-FPM for Nginx on CentOS Stream
Skip this Nginx pool-ownership section when you installed PHP for Apache. Apache also uses PHP-FPM with current AppStream packages, but its default handler expects the packaged apache pool settings. Nginx needs the pool user and socket ownership changed to nginx.
Confirm that the Nginx system user exists before changing PHP-FPM ownership:
id nginx
The command should return an nginx UID and group. If it reports id: 'nginx': no such user on a new Nginx server, sudo dnf install nginx creates the package-owned user on current CentOS Stream releases. Finish the Nginx server setup before editing the PHP-FPM pool.
Set PHP-FPM Pool Ownership for Nginx
Back up the default pool file, then set the worker user, group, and socket ownership to nginx:
sudo cp -a /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak
sudo sed -i -E 's/^user = .*/user = nginx/; s/^group = .*/group = nginx/' /etc/php-fpm.d/www.conf
sudo sed -i -E 's/^;?listen\.owner = .*/listen.owner = nginx/; s/^;?listen\.group = .*/listen.group = nginx/' /etc/php-fpm.d/www.conf
Verify the edited lines:
grep -E '^(user|group|listen\.owner|listen\.group) =' /etc/php-fpm.d/www.conf
Expected output:
user = nginx group = nginx listen.owner = nginx listen.group = nginx
Test the PHP-FPM configuration before starting the service:
sudo php-fpm -tt 2>&1 | grep -o 'configuration file /etc/php-fpm.conf test is successful'
A valid configuration returns:
configuration file /etc/php-fpm.conf test is successful
Start and Verify PHP-FPM
Start PHP-FPM and enable it for future boots:
sudo systemctl enable --now php-fpm
Check the running and enabled state:
systemctl is-active php-fpm
systemctl is-enabled php-fpm
Expected output:
active enabled
Add PHP Handling to an Nginx Server Block
Add this location block inside the Nginx server block that serves your PHP site:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Test the Nginx configuration after saving the server block:
sudo nginx -t
Expected output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload Nginx only after the syntax test passes:
sudo systemctl reload nginx
Update PHP on CentOS Stream
PHP packages update through normal DNF transactions. To refresh metadata and update installed PHP packages only, use a quoted package glob so the shell does not expand it against local filenames:
sudo dnf upgrade --refresh 'php*'
On CentOS Stream 9, DNF stays on the enabled module stream. Switching from one PHP branch to another is a stream-change operation, not a normal update.
Troubleshoot PHP on CentOS Stream
PHP Module Stream Conflicts on CentOS Stream 9
If CentOS Stream 9 already has one PHP stream enabled, DNF can refuse a different stream until you reset the module state.
Check the enabled stream first:
dnf module list php --enabled
Reset the module, enable the target stream, then synchronize installed PHP packages to that branch:
sudo dnf module reset php
sudo dnf module enable php:8.3
sudo dnf distro-sync 'php*'
Replace php:8.3 with php:8.2 or php:8.1 only when your application requires that branch.
PHP-FPM Fails After Nginx Ownership Changes
If PHP-FPM fails to start after changing the pool user to nginx, confirm the Nginx user exists:
id nginx
A missing user looks like this:
id: 'nginx': no such user
Install or restore Nginx before using nginx as the PHP-FPM pool owner. If you need to revert the pool file, restore the backup created earlier and restart PHP-FPM:
sudo cp -a /etc/php-fpm.d/www.conf.bak /etc/php-fpm.d/www.conf
sudo systemctl restart php-fpm
Check the service again:
systemctl is-active php-fpm
A running service returns:
active
PHP Extension Package Is Missing
If an application names a missing extension, search for the matching package name:
dnf list 'php-*extension-name*'
Replace extension-name with the extension family, such as imagick or redis. Some less common packages may require EPEL, so use the separate guide to enable EPEL on CentOS Stream only when AppStream does not provide the extension.
Remove PHP from CentOS Stream
Remove PHP packages only after you have backed up application configuration, pool files, and any site-specific PHP settings you need to keep.
The quoted
'php*'pattern removes installed PHP packages and extensions. Review DNF’s transaction summary before confirming, especially on shared servers where multiple applications may depend on PHP.
If you used PHP-FPM, stop and disable the service first:
sudo systemctl disable --now php-fpm
Remove the PHP packages:
sudo dnf remove 'php*'
On CentOS Stream 9, reset the PHP module stream after removing the packages:
sudo dnf module reset php
Review optional dependency cleanup separately:
sudo dnf autoremove
Verify that the main PHP packages and command are gone:
rpm -q php php-cli php-fpm || true
hash -r
command -v php || echo "php command not found"
Expected output:
package php is not installed package php-cli is not installed package php-fpm is not installed php command not found
This removes PHP, not Apache, Nginx, EPEL, or Remi. Remove those components separately only when no other application on the server uses them.
Conclusion
PHP is installed from CentOS Stream AppStream, with the active branch verified through the CLI and common extensions available through DNF. Apache deployments can use the php package path, while Nginx stacks can hand requests to PHP-FPM over /run/php-fpm/www.sock. For newer PHP branches outside AppStream, use the separate guide to install Remi RPM repository on CentOS Stream.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><a href="https://example.com">link</a><blockquote>quote</blockquote>