Apache is one of the most well-known web servers in the world, mainly known for its stability, performance, and a wide range of available modules. In this article, I will explain the different thread managers and the different modes of executing PHP code and the implications of doing it one way or another.
It is possible to enable PHP support in Apache in several ways:
- mod_php (best option for single-user environments): The fastest mode as long as requests are NOT handled concurrently. If hosting is shared and someone manages to exploit a vulnerability, all files of all clients will be vulnerable since the files generated by Apache belong to the same system user. If it executes code, it will run with the permissions of the Apache user. The PHP interpreter is embedded within Apache, so that binary will be loaded both for serving static and dynamic content, therefore consuming more resources.
- CGI: PHP is executed as an external software, each CGI execution opens and closes the entire execution environment. With this type of execution, we have the same problem as mod_php of a single user for everything, but we can use the suexec module of Apache to execute it with the permissions of the owner of the CGI.
- FastCGI (best option for multi-user environments): The performance level is very similar to mod_php, but it consumes a lot of RAM.
- php-fpm (FastCGI Process Manager): Improved version of FastCGI, allows reloading the php config on the fly, restarting processes without destroying the opcode cache, among other functionalities. It does not support suexec, but through several instances of fpm, we can execute each vhost with a different user.
NOTE: CGI vs FastCGI –> Instead of creating new processes for each request, FastCGI can use a single persistent process that handles any request during its lifetime.
Modifications in execution:
- SuPHP: Same as CGI but allows executing the cgi with the permissions of the cgi owner without using any Apache module like suexec. On the other hand, it consumes a considerable amount of CPU and opcode caching systems cannot be used (the PHP code is recompiled on each request, it is not cached). Due to this limitation, it has become a discardable option in most scenarios.
- SuExec: Apache module that allows us to execute PHP with the indicated user, it does allow opcode caching, and it is only compatible with the execution of PHPs through CGI. Suexec isn’t really required to run cgi-scripts, but it’s a really good idea if you have multiple users serving websites…
SuExec has several parameters that allow us to fine-tune the behavior of PHPs:
- SUEXEC_SAFEPATH: Default PATH for suexec (default: /usr/local/bin:/usr/bin:/bin)
- SUEXEC_LOGFILE: Path to the suexec logfile (default: /var/log/Apache2/suexec_log)
- SUEXEC_CALLER: Name of the user Apache is running as (default: Apache)
- SUEXEC_DOCROOT: Directory in which suexec will run scripts (default: /var/www)
- SUEXEC_MINUID: Minimum UID, which is allowed to run scripts via suexec (default: 1000)
- SUEXEC_MINGID: Minimum GID, which is allowed to run scripts via suexec (default: 100)
- SUEXEC_USERDIR: User subdirectories (like /home/user/html) (default: public_html)
- SUEXEC_UMASK: Umask for the suexec process (default: 077)
For example, if we need a certain umask, it would be as simple as defining it in the Apache compilation:
SUEXEC_UMASK="022"
NOTE: Through cgi/fastcgi, a different php-cgi handler can be indicated for each vhost, allowing us to have a specific version of PHP or php.ini in each vhost.
Resources | mod_php | CGI | FastCGI | suPHP |
---|---|---|---|---|
Memory usage | Low | Low | High | Low |
CPU Usage | Low | High | Low | High |
Security | Low | Low | High | High |
Run as file owner | Mo | No | Yes | Yes |
Overall Performance | Fast | Slow | Fast | Slow |
In addition to the PHP execution method, we must take into account the Apache thread manager ( mpms ):
- worker –> Scalability and concurrency, also recommended if SSL is used. The only downside is that it needs to maintain a thread for each established connection until the timeout is met, even if no traffic is generated. It starts several processes and each of them several threads.
- prefork(default Unix) –> Stability and backward compatibility, suitable when using libraries that do not support threading (such as mod_php). It starts a new process per request.
- itk –> It is experimental and very similar to prefork, it does a chroot in each fork, safer but heavier, each vhost runs with a determined uid and gid.
- peruser(abandoned since 2004) –> Each Apache child runs with its UID and GID, chroots Apache processes, on the other hand, it is not recommended for production, breaks SSL and is not very scalable.
- event –> Like worker but a single thread handles all connections that do not generate traffic, recommended when client traffic is punctual, it is considered unstable.
NOTE: The only mpms with support for threads are worker/event, therefore if we want to execute php as cgi/fastcgi we will not have another option than to compile Apache with mpm –> worker since event is very unstable.
Therefore, the available options are as follows:
MPM | Execution mode |
---|---|
worker | CGI/FastCGI with or without suexec |
prefork | mod_php |
itk | mod_php |
peruser | mod_php |
event | CGI/FastCGI with or without suexec |
We can see the different MPMS when compiling Apache:
Apache2_MPMS="-event -itk -peruser -prefork worker"
The difference between a child process (fork) and a thread of execution (thread) is that processes do not share certain resources with each other, they are independent of each other and communicate through IPC , usually passing through the kernel, while threads do share resources such as the memory of the process that generates them. A multithreaded process generates threads and makes them share these resources and communicate with each other, usually without passing through the kernel. Threads or execution threads are faster than independent processes, but the advantage of child processes is that they are independent and isolated from each other.
NOTE: In order to execute CGI, Apache must be compiled with support for threading, the only stable MPM that supports it is worker, so:
Apache2_MPMS="worker"
An important aspect when compiling Apache is to decide which functionalities it should support, in this way, in addition to obtaining a lighter and faster binary, we will have a more secure Apache since if there is a vulnerability in a module that we have not included, it will not affect us.
We can see the complete list of modules when compiling:
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cgi cgid dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias -asis -auth_digest -authn_dbd -cern_meta -charset_lite -dbd -dumpio -ident -imagemap -log_forensic -proxy -proxy_ajp -proxy_balancer -proxy_connect -proxy_ftp -proxy_http -proxy_scgi -reqtimeout -substitute -version"
NOTE: Depending on the type of MPM we are going to use, we will have to compile Apache with different options.
In the Apache compilation itself, emerge warns us:
Attention: cgi and cgid modules are now handled via Apache2_MODULES flags in make.conf. Make sure to enable those in order to compile them.
In general, you should use 'cgid' with threaded MPMs and 'cgi' otherwise.
If the MPM supports threading:
www-servers/Apache threads
Apache2_MODULES="... cgid ..."
dev-lang/php cgi gd sockets mysql mysqli threads
If it does not support threading:
www-servers/Apache -threads
Apache2_MODULES="... cgi ..."
dev-lang/php Apache2 gd sockets mysql mysqli -threads
In my tests, I have chosen to abandon obsolete or unstable methods, therefore the following will be checked:
- Apache prefork - mod_php:
- Apache ITK - mod_php:
- Apache worker-cgi:
- Apache worker-cgi and suexec:
- Apache worker-fastcgi:
- Apache worker-fastcgi-multiinstance:
Apache prefork - mod_php:
Apache2_MPMS="prefork"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
www-servers/Apache -threads
If we indicate an mpm that does not support threads, such as prefork, but we try to compile Apache with the threads use flag, we will get the following error:
You have selected a non-threaded MPM but USE=threads is enabled
dev-lang/php Apache2 gd sockets mysql mysqli -threads
NOTE: The parameter that indicates that phps will be executed with mod_php is the Apache2 use flag.
We compile Apache:
We compile php:
We indicate to Apache that it should use the internal module:
Apache2_OPTS="............ -D PHP5"
We configure the vhost:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/WEB
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
<Directory "/var/www/WEB">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
</VirtualHost>
We restart the service:
We can check how Apache is being executed by the Apache user:
<?php system('whoami'); ?>
NOTE: All configured vhosts will run with this same user, so a vulnerability in one of the web applications can affect the other vhosts!!
A malicious user could do something like this:
<?php
system("cp /var/www/users/victim/public_html/blog/wp-config.php /var/www/users/pwnerer/hohoho.txt");
?>
We delete the file:
Apache ITK - mod_php:
Apache2_MPMS="itk"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
We compile Apache:
We configure the vhost:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/WEB
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
AssignUserId USER USER
<Directory "/var/www/WEB">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
</VirtualHost>
We indicate to Apache that it should use the internal module:
Apache2_OPTS="............ -D PHP5"
chown -R USER:USER /var/www/WEB
We restart the service:
One way to check that PHP is running with the correct user is through this simple PHP code:
<?php system('whoami'); ?>
It should respond with the name of the user with which you configured the vhost.
We delete the file:
Apache worker-cgi:
To be able to execute PHP with an external CGI, we need an MPM with thread support (worker).
Apache2_MPMS="worker"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cgid dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
We compile Apache with thread support:
www-servers/Apache threads
We compile PHP with support for execution through CGI:
dev-lang/php berkdb bzip2 cli crypt ctype curl curlwrappers exif fileinfo filter ftp gd gdbm hash iconv imap intl json mysql mysqli nls odbc pdo phar posix readline session simplexml soap sockets sqlite3 ssl sysvipc threads tokenizer unicode xml xmlreader xmlrpc xmlwriter zip zlib threads cgi
We compile Apache and PHP:
We configure Apache to use cgi and suexec:
Apache2_OPTS=".... -D CGI"
We create the directory where the php interpreter will be located and, if necessary, the php.ini:
find / -iname php-cgi
cp /usr/bin/php-cgi /var/www/html/cgi-bin/WEB/
chown -R Apache:Apache /var/www/html/cgi-bin/WEB
We configure the vhost indicating what it should do when a php file is requested:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/WEB
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
ScriptAlias /local-bin /var/www/html/cgi-bin/WEB
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi
<Directory "/var/www/html/cgi-bin/WEB">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/WEB">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
</VirtualHost>
We configure Apache to load the cgi module:
#LoadModule cgi_module modules/mod_cgi.so
<IfDefine CGI>
LoadModule cgid_module modules/mod_cgid.so
</IfDefine
We restart the service:
One way to verify that php is running with the correct user is through this simple php:
<?php system('whoami'); ?>
This should respond:
Apache
Apache worker-cgi and suexec:
To be able to run php with an external cgi, we need an mpm with support for threads (worker).
Apache2_MPMS="worker"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cgid dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
We compile Apache with support for threads:
www-servers/Apache threads suexec
We compile php with support for execution through cgi:
dev-lang/php berkdb bzip2 cli crypt ctype curl curlwrappers exif fileinfo filter ftp gd gdbm hash iconv imap intl json mysql mysqli nls odbc pdo phar posix readline session simplexml soap sockets sqlite3 ssl sysvipc threads tokenizer unicode xml xmlreader xmlrpc xmlwriter zip zlib threads cgi
We compile Apache and PHP:
We configure Apache to use CGI and suexec:
Apache2_OPTS=".... -D SUEXEC -D CGI"
We create the directory where the PHP interpreter will be and, if necessary, the php.ini file:
cp /usr/bin/php-cgi /var/www/html/cgi-bin/WEB/
useradd USER
chown -R USER:USER /var/www/html/cgi-bin/WEB
We configure the vhost indicating what it should do when a PHP file is requested:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/WEB
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
SuexecUserGroup USER USER
ScriptAlias /local-bin /var/www/html/cgi-bin/WEB
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi
<Directory "/var/www/html/cgi-bin/WEB">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/WEB">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
</VirtualHost>
We configure Apache to load the CGI module:
#LoadModule cgi_module modules/mod_cgi.so
<IfDefine CGI>
LoadModule cgid_module modules/mod_cgid.so
</IfDefine
We restart the service:
One way to check that PHP is running with the correct user is through this simple PHP code:
<?php system('whoami'); ?>
This should respond with the name of the user configured in the vhost.
Apache worker-fastcgi:
To be able to run PHP with an external CGI, we need an MPM with thread support (worker).
Apache2_MPMS="worker"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cgid dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
We compile Apache with thread support:
www-servers/Apache threads
We compile PHP with support for execution through FastCGI:
dev-lang/php berkdb bzip2 cli crypt ctype curl curlwrappers exif fileinfo filter ftp gd gdbm hash iconv imap intl json mysql mysqli nls odbc pdo phar posix readline session simplexml soap sockets sqlite3 ssl sysvipc threads tokenizer unicode xml xmlreader xmlrpc xmlwriter zip zlib threads fpm cgi
We compile Apache, PHP, and the fastcgi module for Apache:
We configure Apache to use fastcgi:
Apache2_OPTS=".... -D FASTCGI"
LoadModule fastcgi_module modules/mod_fastcgi.so
<IfDefine FASTCGI>
AddHandler fastcgi-script fcg fcgi fpl
</IfDefine>
We create the directory where the PHP interpreter with fastcgi support will be located and, if necessary, the php.ini file:
find / -iname php-fpm
cp /usr/bin/php-fpm /var/www/html/cgi-bin/WEB/
chown -R Apache:Apache /var/www/html/cgi-bin/WEB
We configure the vhost indicating what it should do when a php file is requested:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/WEB
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
ScriptAlias /local-bin /var/www/html/cgi-bin/WEB
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-fpm
FastCgiExternalServer /var/www/html/cgi-bin/WEB/php-fpm -socket /var/run/php-fpm.sock
<Directory "/var/www/html/cgi-bin/WEB">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/WEB">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
</VirtualHost>
listen = /var/run/php-fpm.sock
listen.owner = Apache
listen.group = Apache
user = Apache
group = Apache
If necessary, we modify the umask:
start-stop-daemon --umask 0002 --start --pidfile ${PHP_FPM_PID} --exec /usr/lib/${PHPSLOT}/bin/php-fpm -- -y "${PHP_FPM_CONF}" -g "${PHP_FPM_PID}"
NOTE: By using a Unix socket, we not only gain in performance but also in security since only connections from the local machine will be allowed.
We restart the service:
/etc/init.d/php-fpm restart
One way to check that PHP is running with the correct user is through this simple PHP file:
<?php system('whoami'); ?>
This should respond with the user we have configured php-fpm with, in my case nobody.
Apache worker-fastcgi-multiinstance:
The configuration is very similar to the previous one but in this case we will launch several instances of php-fpm so that each one of them will run with a different user.
Apache2_MPMS="worker"
Apache2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cgid dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias"
We compile Apache with thread support:
www-servers/Apache threads
We compile php with support for execution through fastcgi:
dev-lang/php berkdb bzip2 cli crypt ctype curl curlwrappers exif fileinfo filter ftp gd gdbm hash iconv imap intl json mysql mysqli nls odbc pdo phar posix readline session simplexml soap sockets sqlite3 ssl sysvipc threads tokenizer unicode xml xmlreader xmlrpc xmlwriter zip zlib threads fpm cgi
We compile Apache, php and the fastcgi module for Apache:
We configure Apache to use fastcgi:
Apache2_OPTS=".... -D FASTCGI"
LoadModule fastcgi_module modules/mod_fastcgi.so
<IfDefine FASTCGI>
AddHandler fastcgi-script fcg fcgi fpl
</IfDefine>
We create the directory where the php interpreter with fastcgi support will be located and, if necessary, the php.ini:
useradd user00
mkdir -p /var/www/html/cgi-bin/user00
find / -iname php-fpm
cp /usr/bin/php-fpm /var/www/html/cgi-bin/user00/
chown -R user00:user00 /var/www/html/cgi-bin/user00
mkdir -p /var/www/user00
chown -R user00:user00 /var/www/user00
useradd user01
mkdir -p /var/www/html/cgi-bin/user01
find / -iname php-fpm
cp /usr/bin/php-fpm /var/www/html/cgi-bin/user01/
chown -R user01:user01 /var/www/html/cgi-bin/user01
mkdir -p /var/www/user01
chown -R user01:user01 /var/www/user01
We configure the vhost indicating what it should do when a php file is requested:
Listen 80
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/user00
ServerName alfaexploit.com
ServerAlias www.alfaexploit.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
ScriptAlias /local-bin /var/www/html/cgi-bin/user00
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-fpm
FastCgiExternalServer /var/www/html/cgi-bin/user00/php-fpm -socket /var/run/php-fpm_user00.sock
<Directory "/var/www/html/cgi-bin/user00">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/user00">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
# Monitoring status:
<LocationMatch "/(ping|status)">
SetHandler php-fastcgi-virt
Action php-fastcgi-virt /local-bin/php-fpm virtual
</LocationMatch>
</VirtualHost>
<VirtualHost *:80>
ServerAdmin kr0m@alfaexploit.com
DocumentRoot /var/www/user01
ServerName alfaexploit2.com
ServerAlias www.alfaexploit2.com
ErrorLog /var/log/apache2/alfaexploit.error_log
CustomLog /var/log/apache2/alfaexploit.access_log combined
DirectoryIndex index.php index.htm index.html
ScriptAlias /local-bin /var/www/html/cgi-bin/user01
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-fpm
FastCgiExternalServer /var/www/html/cgi-bin/user01/php-fpm -socket /var/run/php-fpm_user01.sock
<Directory "/var/www/html/cgi-bin/user01">
Options -Indexes ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/user01">
options -Indexes FollowSymLinks
AllowOverride All
order allow,deny
Allow from all
</Directory>
# Monitoring status:
<LocationMatch "/(ping|status)">
SetHandler php-fastcgi-virt
Action php-fastcgi-virt /local-bin/php-fpm virtual
</LocationMatch>
</VirtualHost>
[global]
error_log = /var/log/php-fpm.log
include=/etc/php/fpm-php5.5/pool.d/*.conf
We configure the FPM pools:
[user00]
user = user00
group = user00
listen = /var/run/php5-fpm_user00.sock
listen.owner = Apache
listen.group = Apache
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
ping.path = /ping
ping.response = pong
[user01]
user = user01
group = user01
listen = /var/run/php5-fpm_user01.sock
listen.owner = Apache
listen.group = Apache
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
ping.path = /ping
ping.response = pong
If necessary, we modify the umask:
start-stop-daemon --umask 0002 --start --pidfile ${PHP_FPM_PID} --exec /usr/lib/${PHPSLOT}/bin/php-fpm -- -y "${PHP_FPM_CONF}" -g "${PHP_FPM_PID}"
We restart the service:
/etc/init.d/php-fpm restart
One way to check that php is running with the correct user is through this simple php:
<?php system('whoami'); ?>
<?php system('whoami'); ?>
This should respond with the user we have configured in each php-fpm instance.
FPM provides us with certain information about each of the pools:
URL/ping
With this, we would already have the different configuration modes of Apache, its MPMs, and its ways of executing PHP. In each scenario, indicative performance tests have been carried out. It should be taken into account that the Apache server has been installed and tested on a laptop with X started, Firefox with several tabs, and several desktop applications.
The benchmarks were performed on a 2.26GHz core 2 duo with 4GB of RAM, and the software used for the tests was Apache benchmark:
For plotting, gnuplot was chosen:
sci-visualization/gnuplot X cairo gd qt4 readline wxwidgets -aqua bitmap -doc -examples -ggi -latex -lua plotutils svga -thin-splines
We generate the graph files:
gnuplot> set output “NAME.png”
gnuplot> plot “NAME.csv” using 7 w lines title ‘CTime’, “NAME.csv” using 8 w lines title ‘DTime’, “NAME.csv” using 9 w lines title ‘TTime’, “NAME.csv” using 10 w lines title ‘Wait’
These are the results:
itk_modphp | prefork_modphp | worker_cgi |
---|---|---|
worker_cgi_suexec | worker_fastcgi | comparativa |
---|---|---|
As we can see, the combination that remains most stable when there are several simultaneous requests is the one that uses fast-cgi.