Apache’s PHP module works fine by default and it’s very easy to set up. But, we have several drawbacks:
- Apache PHP module will be loaded every single request, so our RAM usage is higher.
- Prefork has higher CPU usage than Worker. Also prefork has higher RAM usage
So we will attend more clients with less resources, but we will have some trouble with some modules or configurations, like APC, or the number of mysql opened connections (it will increase as the persistent connections will be by thread) but will notice the difference.
First of all, as I say on every page of this tutorial, I’ve tested it in Ubuntu Server 12.04, so it may vary if you use another Linux OS, but the important things I think are similar. You may notice I’m using apt-get to install packages and sudo to execute statements as root, also the name of the packages will vary if you use another distribution.
Contents
Installation
We’ve to install apache Worker MPM, Fcgid module and php-cgi, so:
$ sudo apt-get install apache2-mpm-worker libapache2-mod-fcgis php5-cgi php-apc
It may ask you to uninstall libapache2-mod-php5 or apache-mpm-prefork if it’s installed. On a fresh install it shouldn’t complain.
We are also installing php-apc, it’s an opcode cache to make our server run a little faster. It’s always a good idea, even if we are using Apache Prefork.
Enable FCGId and configure PHP
The next step is to enable mod_fcgid:
$ sudo a2enmod fcgid
After that, we should create a php wrapper script to put there some basic configuration to launch the CGI processes. The file could be located in /usr/bin, /usr/local/bin or even inside our document root (but it’s not reccomended), but we can locate it one level before. In this example, I will put it in /usr/local/bin/php-wrapper with this contents:
PHP_FCGI_MAX_REQUESTS=10000
export PHP_FCGI_MAX_REQUESTS
PHP_FCGI_CHILDREN=5
export PHP_FCGI_CHILDREN
exec /usr/lib/cgi-bin/php5-cgi -d apc.shm_size=50M
The last part: “-d apc.shm_size=50M” is to use 50Mb opcode cache per user. We should tune it depending on the APC Cache usage in our site.
We are also defining PHP_FCGI_MAX_REQUESTS, that is the number of requests before restarting each child process (each child can attend several clients), but it’s a good idea to restart processes to clean up memory from leaks (these leaks may be caused by PHP or by specific scripts causing PHP not to cleanup properly)
PHP_FCGI_CHILDREN is the number of children this instance of php should spawn, it depends on our system resources, we can increase this number depending on our available CPU and RAM and so, we can attend more clients at a time.
/usr/bin/php-fcgi is our php cgi executable path, let’s find
And then, tell Apache to use this configuration. So, in our virtualhost configuration (in the example was /etc/apache2/sites-available/totaki.com, we must insert the following changes (in bold):
<VirtualHost *:80> ServerAdmin info@totaki.com ServerName totaki.com ServerAlias www.totaki.com DocumentRoot /home/cloud/www/totaki.com/www <Ifmodule mod_fcgid.c> # See /etc/apache2/mods-available/fcgid.conf for (fcgid-script) AddHandler fcgid-script .php .php5 .phtml FcgidWrapper /usr/local/bin/php-wrapper .php FcgidWrapper /usr/local/bin/php-wrapper .php5 FcgidWrapper /usr/local/bin/php-wrapper .phtml </IfModule> <Directory /> Options FollowSymLinks AllowOverride All</Directory> <Directory /home/cloud/www/totaki.com/www/> Options FollowSymLinks MultiViews +ExecCGI AllowOverride All Order allow,deny allow from all</Directory> ErrorLog "/home/cloud/www/totaki.com/logs/error.log" LogLevel warn CustomLog "/home/cloud/www/totaki.com/logs/access.log" combined</VirtualHost>
Just restarting the server, we can have it working with PHP-CGI, as we can see creating a sample info script:
Custom PHP.INI file for each Virtualhost
We cannot use php_value in .htaccess with this configuration, but we can set a custom php.ini file for each VirtualHost, setting PHPRC in our VirtualHost configuration or in our PHP Wrapper. In this example, I show you the VirtualHost configuration:
<VirtualHost *:80> ServerAdmin info@totaki.com ServerName totaki.com ServerAlias www.totaki.com DocumentRoot /home/cloud/www/totaki.com/www <Ifmodule mod_fcgid.c> # See /etc/apache2/mods-available/fcgid.conf for (fcgid-script) AddHandler fcgid-script .php .php5 .phtml FcgidInitialEnv PHPRC "/home/cloud/www/totaki.com/php/" FcgidWrapper /usr/local/bin/php-wrapper .php FcgidWrapper /usr/local/bin/php-wrapper .php5 FcgidWrapper /usr/local/bin/php-wrapper .phtml </IfModule> <Directory /> Options FollowSymLinks AllowOverride All </Directory> <Directory /home/cloud/www/totaki.com/www/> Options FollowSymLinks MultiViews +ExecCGI AllowOverride All Order allow,deny allow from all </Directory> ErrorLog "/home/cloud/www/totaki.com/logs/error.log" LogLevel warn CustomLog "/home/cloud/www/totaki.com/logs/access.log" combined </VirtualHost>
Then we put a php.ini file in /home/cloud/www/totaki.com/www. Remember each VirtualHost can have a different PHPRC configuration, just if the have a different ServerName.
System wide CGI configuration
It’s recommended to have some common settings outside the VirtualHost configuration. We can see all available Fcgid settings here, but I will post here what I use more frequently. Some of these configurations can be also set in the VirtualHost. But I will create /etc/apache2/conf.d/cgisettings.conf:
<IfModule mod_fcgid.c> FcgidBusyScanInterval 10 FcgidMaxProcesses 20 FcgidMaxRequestLen 1073741824 </IfModule>
Here:
- FcgidBusyScanInterval: is the time the process look for busy childs.
- FcgidMaxProccesses: is the number of total CGI processes to launch
- FcgidMaxRequestLen: is the total size of a request. It is useful if you have applications which upload files, for example. In the past, it had a big value but now don’t
We can also use the directive: FcgidMaxProcessesPerClass which set the maximum number of processes that will be launch per VirtualHost.
Shellshock bug
It’s important to have the latest bash installed. Because Shellshock bug is easy to exploit with this configuration.
Leave a Reply