Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

mod_php Explained: PHP Inside the Apache Process

With mod_php, PHP sits inside every Apache process. That is simple but inflexible, and after PHP2Shell it is the riskiest operating mode. How it works and how to recognise it.

Last updated 5 min readPHP knowledge

In short: mod_php is PHP as a module in the Apache web server. Every Apache process then contains a complete PHP interpreter and executes PHP code itself; the SAPI is called apache2handler. It is easy to set up but ties PHP to Apache, usually requires the prefork MPM and allows hardly any separation between websites. The PHP manual advises against it for new installations, and with PHP2Shell the PHP team rates the risk highest for mod_php.

What is mod_php?

With mod_php, Apache loads PHP as its own module into its processes. There is no separate PHP service: when Apache is to serve a .php file, the same process that accepted the request also executes the PHP code. For many years this was the standard way to run PHP, and it is still common on older servers and in some Docker images today.

According to the PHP manual, PHP as a server module reads its configuration only once, when the web server starts. Changes to php.ini and updates of the module therefore take effect only after a restart of Apache.

Important for understanding: Apache processes live for a long time. A process accepts many connections one after another before it is replaced; how many is governed by the Apache directive MaxConnectionsPerChild. The embedded PHP interpreter stays the same during this time. Replacing the libphp library on disk changes nothing about the running processes.

For management and project leads this can be summarised as follows: with mod_php, web server and PHP are one unit. Touching one affects the other. A PHP update means a restart of the web server, a flaw in PHP runs with the web server's privileges, and separation between several websites on the same server is hardly possible.

How is mod_php integrated?

The PHP manual shows the integration in two steps: load the module and define which files PHP is to process.

LoadModule php_module modules/libphp.so

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

The manual recommends FilesMatch with SetHandler rather than just AddType, so that uploaded files such as bild.php.jpg are not executed as PHP. On Debian and Ubuntu, packages such as libapache2-mod-php8.3 and the commands a2enmod and a2dismod take care of this.

Whether mod_php is active can be checked read-only:

apachectl -M 2>/dev/null | grep -i php    # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php        # RHEL family
apachectl -V | grep -i mpm               # active MPM (prefork, worker, event)

Prefork, thread safety and resources

Apache distributes requests through a multi-processing module (MPM). According to the PHP manual, mod_php requires the prefork MPM unless PHP was built with Zend Thread Safety (--enable-zts). Most distribution packages are built without thread safety.

Prefork means: one process per simultaneous connection, and each process carries a complete PHP interpreter. Even requests for images or CSS files thus occupy a process with PHP in its baggage. This costs memory and limits the load a server can carry.

Feature mod_php PHP-FPM
Where does PHP run? in every Apache process in its own service
Apache MPM usually prefork event possible
User per website no, everything as the Apache user yes, per pool
Restarting PHP only together with Apache independent of Apache
Settings per directory php_value in .htaccess pool or .user.ini

For this reason the manual recommends PHP-FPM with mod_proxy_fcgi for all modern installations: better resource management, process separation, restarting PHP without restarting Apache, and compatibility with the event MPM, which has been the default since Apache 2.4. The basics are under PHP-FPM explained.

Settings with .htaccess, php_value and php_admin_value

With mod_php, PHP settings can be set directly in the Apache configuration. The manual distinguishes between change modes: entries marked INI_PERDIR may appear in php.ini, .htaccess or httpd.conf, entries marked INI_SYSTEM only in php.ini or httpd.conf.

# In the VirtualHost configuration: locked against the application
php_admin_flag  display_errors off
php_admin_value upload_max_filesize 24M

# Possible in .htaccess, but can be overridden by the application
php_value max_execution_time 60

php_admin_value and php_admin_flag are allowed only in the server configuration, not in .htaccess. This very distinction is important for the interim measures for PHP2Shell, because values such as session.upload_progress.enabled must not be reset by the application.

mod_php and PHP2Shell: why the risk is highest

The PHP team rates the risk from PHP2Shell highest for mod_php: an exploit was demonstrated there before any application code runs at all. Security plugins or checks in the CMS therefore come too late. In addition, with mod_php, PHP runs with the privileges and in the memory of the web server. The detailed assessment is under Why mod_php carries the highest risk.

For operators this means:

  1. Update the PHP module to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a confirmed backport.
  2. Restart Apache completely, not just reload it, and check the start time of the processes.
  3. Set interim values via php_admin_value in the server configuration if the update is not yet possible.
  4. Then plan the move to PHP-FPM, as described under Securing Apache with mod_php.

How does PHP SOS help?

  • Detect: We check on which servers mod_php is running, with which MPM and from which package source.
  • Patch: We update the PHP module, restart Apache completely and document the state.
  • Secure the interim period: Where the update is blocked, we set the php.net measures as locked values in the server configuration.
  • Switch over: As part of server hardening we migrate to PHP-FPM with separate pools, tested beforehand.

Frequently asked questions

Why is it called mod_php when the module is named php_module?

mod_php is the colloquial name for PHP as an Apache module. In the configuration it is loaded with LoadModule; the PHP manual gives LoadModule php_module modules/libphp.so as an example. Older versions used names such as php7_module or php5_module.

Why does mod_php need the prefork MPM?

According to the PHP manual, mod_php requires the prefork MPM unless PHP was built with Zend Thread Safety. Most distribution packages are built without thread safety. Prefork starts a separate process for every simultaneous connection, which needs more memory.

Do php_value lines in .htaccess also work with PHP-FPM?

No. php_value and php_flag in .htaccess are Apache directives of the PHP module and only work with mod_php. Under PHP-FPM, such settings belong in the pool or, for permitted values, in a .user.ini.

Do I have to abandon mod_php immediately?

The PHP update with a complete restart of Apache comes first. Switching to PHP-FPM makes sense afterwards but should be planned and tested. It does not close PHP2Shell, because PHP-FPM is affected as well.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help