How to Install and Use mod_php in Apache

How to install and use mod_php in Apache

How to install and use mod_php in Apache

PHP and Apache have a long history together, and mod_php is the classic way to get them talking to each other. I’ve used it on plenty of smaller sites and legacy applications over the years — it’s dead simple to set up compared to alternatives like PHP-FPM, even if it’s not always my first choice for high-traffic production environments anymore. In this post, I’ll walk through installing and configuring mod_php, and I’ll also be honest with you about when I’d reach for something else instead.

What Is mod_php

mod_php is an Apache module that embeds the PHP interpreter directly inside Apache’s worker processes. When a request comes in for a .php file, Apache hands it off internally to the embedded PHP interpreter, which executes the script and returns the output — all within the same process, no separate service required.

This is different from PHP-FPM (FastCGI Process Manager), which runs PHP as a completely separate process pool that Apache (or Nginx) communicates with over a socket or TCP connection. mod_php is simpler to set up, but it ties PHP execution to Apache’s process model, which has real implications for performance and memory usage that I’ll get into.

Prerequisites

Important: mod_php Requires the Prefork MPM

This is the detail that trips people up most often. mod_php is not thread-safe, so it only works with Apache’s prefork Multi-Processing Module, which handles each request in a separate process rather than a thread. If your Apache is running worker or event MPM (common on fresh installs), you’ll need to switch.

Check your current MPM:

apachectl -V | grep -i mpm

Switch to prefork on Debian/Ubuntu:

sudo a2dismod mpm_event mpm_worker
sudo a2enmod mpm_prefork
sudo systemctl restart apache2

On CentOS/RHEL, edit /etc/httpd/conf.modules.d/00-mpm.conf and comment/uncomment the relevant LoadModule lines to select mpm_prefork_module.

Step 1: Install PHP and mod_php

Debian/Ubuntu

sudo apt update
sudo apt install php libapache2-mod-php

This automatically enables the module and restarts Apache appropriately, but I always double check:

apachectl -M | grep php

CentOS/RHEL

sudo dnf install php php-cli
sudo systemctl restart httpd

On RHEL-based systems, the Apache PHP module typically loads automatically once the package is installed — confirm with:

apachectl -M | grep php

Step 2: Verify PHP Is Working

Create a test file in your document root:

sudo nano /var/www/html/info.php
<?php
phpinfo();
?>

Visit http://your-server-ip/info.php in a browser. If you see the PHP info page, everything’s wired up correctly.

Important: Delete this file once you’ve confirmed it works. phpinfo() exposes a lot of server configuration detail that shouldn’t be publicly accessible.

sudo rm /var/www/html/info.php

Step 3: Configure PHP Settings

The main PHP config file is php.ini, typically located at:

Common settings I adjust right away:

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 60
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log

In production, display_errors should always be Off — you don’t want PHP stack traces visible to visitors. Errors should go to a log file instead, where you can review them without exposing internal details.

After editing php.ini, restart Apache to apply changes:

sudo systemctl restart apache2   # Debian/Ubuntu
sudo systemctl restart httpd     # CentOS/RHEL

Step 4: Per-Directory PHP Configuration

Sometimes I need different PHP settings for a specific site or directory — for instance, a larger upload limit just for an admin upload tool. I do this in the virtual host or a .htaccess file:

<Directory /var/www/example.com/uploads>
    php_value upload_max_filesize 128M
    php_value post_max_size 128M
</Directory>

Note: php_value/php_admin_value directives only work with mod_php — this is actually one of its conveniences over PHP-FPM, where per-directory PHP settings require separate pool configs.

Installing PHP Extensions

Most applications (WordPress, Laravel, etc.) need specific PHP extensions. Common ones:

# Debian/Ubuntu
sudo apt install php-mysql php-curl php-gd php-mbstring php-xml php-zip

# CentOS/RHEL
sudo dnf install php-mysqlnd php-curl php-gd php-mbstring php-xml php-zip

Restart Apache after installing any new extension:

sudo systemctl restart apache2   # Debian/Ubuntu
sudo systemctl restart httpd     # CentOS/RHEL

mod_php vs PHP-FPM: My Honest Take

I want to be upfront about this since it affects real decisions:

mod_php pros:

mod_php cons:

For anything with meaningful traffic, I switch to PHP-FPM with Apache’s event MPM and mod_proxy_fcgi. But for smaller sites, dev environments, or legacy applications that assume mod_php-style behavior, it’s still a perfectly reasonable choice, and I won’t pretend otherwise.

Switching PHP Versions with mod_php

Because mod_php binds a single PHP version directly into Apache, switching versions on Debian/Ubuntu (where multiple PHP versions can be installed side by side) requires disabling one module and enabling another:

sudo a2dismod php8.1
sudo a2enmod php8.3
sudo systemctl restart apache2

Check which version is now actually active:

php -v
apachectl -M | grep php

This works fine for a single site that needs to move to a newer PHP version, but if you’re hosting multiple sites that each need a different PHP version simultaneously, mod_php genuinely can’t do that — only one version can be loaded into Apache at a time. That’s the scenario where I stop reaching for mod_php entirely and set up PHP-FPM instead, running a separate pool per version, each proxied through mod_proxy_fcgi to the appropriate socket per virtual host.

Real-World Use Cases

Troubleshooting Tips

Common Mistakes to Avoid

  1. Leaving phpinfo() accessible publicly — remove test files immediately after checking them.
  2. Running event/worker MPM with mod_php enabled, which simply won’t work.
  3. Leaving display_errors On in production, exposing internal paths and logic to visitors.
  4. Forgetting to restart Apache after installing new PHP extensions.
  5. Assuming mod_php will scale like PHP-FPM under heavy load — it won’t, due to the process-per-request model tied to Apache’s prefork workers.

Security Best Practices

Performance Optimization

opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2

Frequently Asked Questions

Q: Do I need mod_php or can I just install PHP separately? A: For Apache to execute PHP files directly, you need either mod_php or a FastCGI setup like PHP-FPM with mod_proxy_fcgi. PHP alone isn’t enough.

Q: Why does mod_php require the prefork MPM? A: Because mod_php isn’t thread-safe — it needs each request handled in its own process, which is exactly what prefork provides.

Q: Is mod_php deprecated? A: Not deprecated, but increasingly less recommended for production due to performance and scalability limitations compared to PHP-FPM.

Q: Can I run multiple PHP versions with mod_php? A: It’s difficult — mod_php binds one PHP version directly into Apache. Running multiple versions simultaneously is much easier with PHP-FPM, where you can run separate pools per version.

Q: How do I check which PHP version is running? A: Run php -v from the CLI, or check phpinfo() output temporarily (then remove it).

Summary and Key Takeaways

mod_php is a straightforward way to get PHP running under Apache, especially for smaller projects. Here’s what to remember:

It’s a solid, simple option — just go in with clear eyes about its scaling limitations.

References

Exit mobile version