This page looks best with JavaScript enabled

Apache with PHP support on Gentoo

 ·  🎃 kr0m

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:

vi /etc/make.conf
SUEXEC_UMASK="022"
emerge -av Apache

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:

emerge -av www-servers/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:

vi /etc/make.conf
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:

emerge -av Apache
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:

vi /etc/portage/package.use/Apache

www-servers/Apache threads
vi /etc/make.conf
Apache2_MODULES="... cgid ..."
vi /etc/portage/package.use/php
dev-lang/php cgi gd sockets mysql mysqli threads

If it does not support threading:

vi /etc/portage/package.use/Apache

www-servers/Apache -threads
vi /etc/make.conf
Apache2_MODULES="... cgi ..."
vi /etc/portage/package.use/php
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:

vi /etc/make.conf
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"
vi /etc/portage/package.use/Apache
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
vi /etc/portage/package.use/php
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:

emerge -av Apache

We compile php:

emerge -av php

We indicate to Apache that it should use the internal module:

vi /etc/conf.d/Apache2

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>
chown -R Apache:Apache /var/www/WEB

We restart the service:

/etc/init.d/Apache2 restart

We can check how Apache is being executed by the Apache user:

vi /var/www/WEB/w.php
<?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:

rm /var/www/WEB/w.php


Apache ITK - mod_php:

vi /etc/make.conf
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:

emerge -av 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:

vi /etc/conf.d/Apache2

Apache2_OPTS="............ -D PHP5"
useradd USER
chown -R USER:USER /var/www/WEB

We restart the service:

/etc/init.d/Apache restart

One way to check that PHP is running with the correct user is through this simple PHP code:

vi /var/www/WEB/w.php

<?php system('whoami'); ?>
chown USER:USER /var/www/WEB/w.php

It should respond with the name of the user with which you configured the vhost.

We delete the file:

rm /var/www/WEB/w.php


Apache worker-cgi:

To be able to execute PHP with an external CGI, we need an MPM with thread support (worker).

vi /etc/make.conf

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:

vi /etc/portage/package.use/Apache

www-servers/Apache threads

We compile PHP with support for execution through CGI:

vi /etc/portage/package.use/php

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:

emerge -av Apache php

We configure Apache to use cgi and suexec:

vi /etc/conf.d/Apache2

Apache2_OPTS=".... -D CGI"

We create the directory where the php interpreter will be located and, if necessary, the php.ini:

mkdir -p /var/www/html/cgi-bin/USER
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>
chown -R Apache:Apache /var/www/WEB

We configure Apache to load the cgi module:

vi /etc/Apache2/httpd.conf

#LoadModule cgi_module modules/mod_cgi.so
<IfDefine CGI>
LoadModule cgid_module modules/mod_cgid.so
</IfDefine

We restart the service:

/etc/init.d/Apache2 restart

One way to verify that php is running with the correct user is through this simple php:

vi /var/www/WEB/w.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).

vi /etc/make.conf

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:

vi /etc/portage/package.use/Apache

www-servers/Apache threads suexec

We compile php with support for execution through cgi:

vi /etc/portage/package.use/php

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:

emerge -av Apache php

We configure Apache to use CGI and suexec:

vi /etc/conf.d/Apache2

Apache2_OPTS=".... -D SUEXEC -D CGI"

We create the directory where the PHP interpreter will be and, if necessary, the php.ini file:

mkdir -p /var/www/html/cgi-bin/WEB
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>
chown -R USER:USER /var/www/WEB

We configure Apache to load the CGI module:

vi /etc/Apache2/httpd.conf

#LoadModule cgi_module modules/mod_cgi.so
<IfDefine CGI>
LoadModule cgid_module modules/mod_cgid.so
</IfDefine

We restart the service:

/etc/init.d/Apache2 restart

One way to check that PHP is running with the correct user is through this simple PHP code:

vi /var/www/WEB/w.php

<?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).

vi /etc/make.conf

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:

vi /etc/portage/package.use/Apache

www-servers/Apache threads

We compile PHP with support for execution through FastCGI:

vi /etc/portage/package.use/php

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:

emerge -av Apache php www-Apache/mod_fastcgi

We configure Apache to use fastcgi:

vi /etc/conf.d/Apache2

Apache2_OPTS=".... -D FASTCGI"
vi /etc/Apache2/httpd.conf
LoadModule fastcgi_module modules/mod_fastcgi.so
vi /etc/Apache2/modules.d/20_mod_fastcgi.conf
<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:

mkdir -p /var/www/html/cgi-bin/WEB
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>
vi /etc/php/fpm-php5.5/php-fpm.conf
listen = /var/run/php-fpm.sock
listen.owner = Apache
listen.group = Apache
user = Apache
group = Apache

If necessary, we modify the umask:

vi /etc/init.d/php-fpm

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.

chown -R Apache:Apache /var/www/WEB

We restart the service:

/etc/init.d/Apache2 restart
/etc/init.d/php-fpm restart

One way to check that PHP is running with the correct user is through this simple PHP file:

vi /var/www/WEB/w.php

<?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.

vi /etc/make.conf
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:

vi /etc/portage/package.use/Apache

www-servers/Apache threads

We compile php with support for execution through fastcgi:

vi /etc/portage/package.use/php

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:

emerge -av Apache php www-Apache/mod_fastcgi

We configure Apache to use fastcgi:

vi /etc/conf.d/Apache2

Apache2_OPTS=".... -D FASTCGI"
vi /etc/Apache2/httpd.conf
LoadModule fastcgi_module modules/mod_fastcgi.so
vi /etc/Apache2/modules.d/20_mod_fastcgi.conf
<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>
vi /etc/php/fpm-php5.5/php-fpm.conf
[global]
error_log = /var/log/php-fpm.log
include=/etc/php/fpm-php5.5/pool.d/*.conf

We configure the FPM pools:

vi /etc/php/fpm-php5.5/pool.d/user00.conf

[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
vi /etc/php/fpm-php5.5/pool.d/user01.conf
[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:

vi /etc/init.d/php-fpm

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/Apache2 restart
/etc/init.d/php-fpm restart

One way to check that php is running with the correct user is through this simple php:

vi /var/www/user00/w.php

<?php system('whoami'); ?>
vi /var/www/user01/w.php
<?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/status
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:

ab -n100000 -c50 -g NAME.csv http://WEB/ –> 100000 requests and 50 concurrent requests.

For plotting, gnuplot was chosen:

vi /etc/portage/package.use/gnuplot

sci-visualization/gnuplot X cairo gd qt4 readline wxwidgets -aqua bitmap -doc -examples -ggi -latex -lua plotutils svga -thin-splines
emerge -av sci-visualization/gnuplot

We generate the graph files:

gnuplot> set terminal png
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.

If you liked the article, you can treat me to a RedBull here