# mod_php Explained: PHP Inside the Apache Process

> mod_php explained: how PHP runs as an Apache module, how to recognise it, what prefork and .htaccess mean for it and why php.net advises against it.

Source: https://phpsos.de/en/php/mod-php-erklaert/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**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.

```apache
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:

```bash
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](https://phpsos.de/en/php/php-fpm-erklaert/).

## 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`.

```apache
# 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](https://phpsos.de/en/php2shell/mod-php-risiko/).

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](https://phpsos.de/en/server/apache-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](https://phpsos.de/en/leistungen/server-haertung/) 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

- [PHP Manual: Apache 2.x on Unix Systems](https://www.php.net/manual/en/install.unix.apache2.php)
- [PHP Manual: Where a Configuration Setting May Be Set](https://www.php.net/manual/en/configuration.changes.modes.php)
- [Apache Documentation](https://httpd.apache.org/docs/)
- [php.net: Security Announcements](https://www.php.net/)
