
How to Configure Apache HTTP with MPM Event and PHP-FPM on Ubuntu 24
Configuring Apache with MPM Event and PHP-FPM on Ubuntu 24 is crucial for modern web applications that demand high performance and scalability. This setup separates the web server from PHP processing, allowing each component to handle what it does best – Apache serves static content efficiently while PHP-FPM manages dynamic content with better resource control and stability. You’ll learn how to implement this architecture from scratch, optimize performance settings, and troubleshoot common issues that crop up in production environments.
Understanding MPM Event and PHP-FPM Architecture
MPM Event represents Apache’s most advanced multi-processing module, designed specifically for high-traffic scenarios. Unlike traditional MPM Prefork that spawns one process per connection, MPM Event uses an event-driven architecture where worker threads handle multiple connections simultaneously. This approach dramatically reduces memory usage and improves concurrent connection handling.
PHP-FPM (FastCGI Process Manager) operates as a separate daemon that manages PHP processes independently from Apache. When a PHP request arrives, Apache forwards it to PHP-FPM via FastCGI protocol, processes the response, and returns it to the client. This separation provides several advantages:
- Independent scaling of web server and PHP processes
- Better fault isolation – PHP crashes don’t affect Apache
- Superior memory management and process recycling
- Granular performance monitoring and logging
- Multiple PHP versions can run simultaneously
Feature | MPM Prefork + mod_php | MPM Event + PHP-FPM |
---|---|---|
Memory Usage | High (PHP loaded in every process) | Low (PHP processes separate) |
Concurrent Connections | Limited by process count | High (event-driven) |
Static File Performance | Good | Excellent |
PHP Performance | Good | Better with optimized pools |
Resource Isolation | Poor | Excellent |
Step-by-Step Installation and Configuration
Start with a fresh Ubuntu 24.04 system and ensure it’s updated:
sudo apt update && sudo apt upgrade -y
sudo reboot
Install Apache with MPM Event support and PHP-FPM:
sudo apt install apache2 apache2-utils
sudo apt install php8.3-fpm php8.3-cli php8.3-common php8.3-mysql php8.3-xml php8.3-curl php8.3-gd php8.3-mbstring php8.3-zip
Verify that MPM Event is the active module:
apache2ctl -M | grep mpm
# Should show: mpm_event_module
If MPM Prefork is active instead, switch to MPM Event:
sudo a2dismod mpm_prefork
sudo a2dismod php8.3
sudo a2enmod mpm_event
sudo systemctl restart apache2
Enable necessary modules for PHP-FPM integration:
sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enmod rewrite
sudo systemctl restart apache2
Configure PHP-FPM by editing the main pool configuration:
sudo nano /etc/php/8.3/fpm/pool.d/www.conf
Optimize the pool settings for better performance:
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500
; Performance and monitoring
pm.status_path = /fpm-status
ping.path = /fpm-ping
slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 5s
; Security
security.limit_extensions = .php .php3 .php4 .php5 .php7 .php8
Create an Apache virtual host configuration that integrates with PHP-FPM:
sudo nano /etc/apache2/sites-available/example.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# PHP-FPM Configuration
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
# Static file caching
<LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$">
ExpiresActive On
ExpiresDefault "access plus 1 month"
Header append Cache-Control "public"
</LocationMatch>
# Logs
ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
# FPM status (restrict access in production)
<Location "/fpm-status">
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
Require ip 127.0.0.1
</Location>
</VirtualHost>
Create the document root and test files:
sudo mkdir -p /var/www/example.com
sudo chown -R www-data:www-data /var/www/example.com
# Create a PHP test file
sudo tee /var/www/example.com/info.php << 'EOF'
<?php
phpinfo();
echo "<h2>Server API: " . php_sapi_name() . "</h2>";
echo "<h2>Server Software: " . $_SERVER['SERVER_SOFTWARE'] . "</h2>";
?>
EOF
Enable the site and restart services:
sudo a2ensite example.conf
sudo a2enmod headers expires
sudo systemctl restart apache2
sudo systemctl restart php8.3-fpm
Performance Optimization and Tuning
Fine-tune MPM Event settings based on your server resources. Edit the Apache configuration:
sudo nano /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 1000
# For high-traffic sites
ServerLimit 16
AsyncRequestWorkerFactor 2
</IfModule>
The optimal settings depend on your hardware specifications:
Server Specs | MaxRequestWorkers | PHP-FPM max_children | ThreadsPerChild |
---|---|---|---|
1 CPU, 1GB RAM | 150 | 10 | 25 |
2 CPU, 2GB RAM | 300 | 25 | 25 |
4 CPU, 4GB RAM | 400 | 50 | 25 |
8 CPU, 8GB RAM | 800 | 100 | 50 |
Configure PHP-FPM process management for optimal memory usage:
sudo nano /etc/php/8.3/fpm/php.ini
; Memory optimization
memory_limit = 128M
max_execution_time = 30
max_input_time = 30
post_max_size = 32M
upload_max_filesize = 32M
; OPcache settings
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
Real-World Use Cases and Examples
This configuration excels in several scenarios commonly encountered in production environments:
High-Traffic WordPress Sites: A WordPress site handling 10,000+ concurrent users benefits significantly from this setup. Static assets like images and CSS files are served directly by Apache’s efficient event-driven architecture, while PHP-FPM processes dynamic content in isolated pools.
API Backends: REST APIs built with frameworks like Laravel or Symfony perform exceptionally well since PHP-FPM can be tuned specifically for API response times while Apache handles CORS headers and rate limiting.
Multi-tenant Applications: You can configure separate PHP-FPM pools for different applications or clients:
# Create separate pool for client A
sudo cp /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/clienta.conf
sudo nano /etc/php/8.3/fpm/pool.d/clienta.conf
[clienta]
user = clienta
group = clienta
listen = /run/php/php8.3-fpm-clienta.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
; Custom PHP settings for this client
php_admin_value[memory_limit] = 256M
php_admin_value[max_execution_time] = 60
For demanding applications, consider upgrading to a dedicated server that provides the resources needed for optimal performance tuning.
Common Issues and Troubleshooting
502 Bad Gateway Errors: Usually indicates PHP-FPM connectivity issues. Check if the service is running and socket permissions are correct:
sudo systemctl status php8.3-fpm
sudo ls -la /run/php/
sudo chmod 660 /run/php/php8.3-fpm.sock
sudo chown www-data:www-data /run/php/php8.3-fpm.sock
Performance Degradation: Monitor PHP-FPM pool status to identify bottlenecks:
# Add this to your virtual host for monitoring
curl http://yoursite.com/fpm-status?full
Memory Issues: If processes consume excessive memory, implement process recycling:
# In pool configuration
pm.max_requests = 500
pm.process_idle_timeout = 10s
Socket vs TCP Performance: Unix sockets typically outperform TCP connections for local communication, but TCP might be necessary for distributed setups:
# TCP configuration (if needed)
listen = 127.0.0.1:9000
# In Apache virtual host:
SetHandler "proxy:fcgi://127.0.0.1:9000"
Debugging Connection Issues: Enable detailed logging to troubleshoot problems:
sudo nano /etc/php/8.3/fpm/php-fpm.conf
log_level = debug
error_log = /var/log/php8.3-fpm.log
Security Best Practices
Implement security hardening to protect your server configuration:
# Create restricted user for PHP-FPM pools
sudo adduser --system --group --no-create-home --shell /bin/false phpapp
sudo usermod -a -G www-data phpapp
Configure PHP-FPM security settings:
# In pool configuration
security.limit_extensions = .php
php_admin_value[open_basedir] = /var/www/example.com:/tmp
php_admin_flag[allow_url_fopen] = off
php_admin_flag[allow_url_include] = off
Set up proper file permissions:
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/example.com
This configuration provides a robust foundation for high-performance web applications. For applications requiring guaranteed resources and maximum performance, consider deploying on a VPS with dedicated CPU and memory allocation. Regular monitoring and gradual tuning based on actual traffic patterns will help you achieve optimal performance for your specific use case.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.