Apache 2.2 on Debian Wheezy w/ PHP-FPM, FastCGI, APC and a kind of suEXEC

Apache / Debian / PHP

won’t talk about pros and cons of PHP-FPM, FastCGI, APC and all that stuff, there are tons of articels around, see also the links below.

main urge was to speed up PHP with APC, get rid of preforked Apaches, run PHP scripts as their native user and many more.

just giving an overview how I’ve easily set it up here, having different „customers“ programming their own PHP scripts and also Debian packages ready to run.

intro

main requirements have been:

  • Opcode Cache
  • every PHP script should run as the same user the virtualhost is owned
  • Debian packages should still run as www-data
  • run Apache as MPM Worker

install

install all the required packages.

aptitude install apache2-mpm-worker libapache2-mod-fastcgi php5-fpm php-apc

enable needed modules.

a2enmod actions alias fastcgi

config

create config file for PHP-FPM and FastCGI in /etc/apache2/conf.d/php5-fpm.

# Configure all that stuff needed for using PHP-FPM as FastCGI

# Set handlers for PHP files.
# application/x-httpd-php                        phtml pht php
# application/x-httpd-php3                       php3
# application/x-httpd-php4                       php4
# application/x-httpd-php5                       php
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>
# application/x-httpd-php-source                 phps
<FilesMatch ".+\.phps$">
    SetHandler application/x-httpd-php-source
    # Deny access to raw php sources by default
    # To re-enable it's recommended to enable access to the files
    # only in specific virtual host or directory
    Order Deny,Allow
    Deny from all
</FilesMatch>

# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(p[345]?|t|tml|ps)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

# Define Action and Alias needed for FastCGI external server.
Action application/x-httpd-php /fcgi-bin/php5-fpm virtual
Alias /fcgi-bin/php5-fpm /fcgi-bin-php5-fpm
<Location /fcgi-bin/php5-fpm>
  # here we prevent direct access to this Location url,
  # env=REDIRECT_STATUS will let us use this fcgi-bin url
  # only after an internal redirect (by Action upper)
  Order Deny,Allow
  Deny from All
  Allow from env=REDIRECT_STATUS
</Location>
FastCgiExternalServer /fcgi-bin-php5-fpm -socket /var/run/php5-fpm.sock -pass-header Authorization

for every PHP file a Handler will be set and also some access restrictions. for the Handler a virtual Action is defined. virtual here means it will not be checked if the given file exists. the Alias is needed in any case, especially later when you go for running PHP as an other user. be careful with the Alias directory-path, don’t use any slashes as described here.

at this point you should be already able to run PHP scripts with PHP-FPM as user www-data with APC enabled. but the main focus here is on running PHP scripts just as an other user. lets go forward.

let’s party

create a new user and add www-data into its group.

adduser --disabled-login tux
adduser www-data tux

create the documentroot and set permissions.

 mkdir -p /var/www/tux/htdocs
chown -R tux:tux /var/www/tux
chmod 755 /var/www/tux
chmod 750 /var/www/tuc/htdocs

looks like overkill to have only the htdocs directory, but be prepared for some directories like log, session, tmp, …

a small index.php for tux could have the following code. keep care of ownership and permissions.

<?php
  system('whoami');
  phpinfo();
?>

splash into the pool

create an additional PHP-FPM pool for user tux by just copying www.conf.

[tux]
user = tux
group = tux

listen = /var/run/php5-fpm-tux.sock

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

chdir = /

restart PHP-FPM.

service php5-fpm restart

check if new PHP-FPM instances are running.

ps -ef | grep php-fpm

 

root     12065     1  0 15:36 ?        00:00:00 php-fpm: master process [...]
www-data 12066 12065  0 15:36 ?        00:00:00 php-fpm: pool www
www-data 12067 12065  0 15:36 ?        00:00:00 php-fpm: pool www
tux      12068 12065  0 15:36 ?        00:00:00 php-fpm: pool tux
tux      12069 12065  0 15:36 ?        00:00:00 php-fpm: pool tux

create a virtual host config for which tux is the owner.

<VirtualHost *:80>
  ServerName tux.kmplabs.org

  ServerAdmin webmaster@kmplabs.org

  DocumentRoot /var/www/tux/htdocs
  <Directory /var/www/tux/htdocs/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  Alias /fcgi-bin/php5-fpm /fcgi-bin-php5-fpm-tux
  FastCgiExternalServer /fcgi-bin-php5-fpm-tux -socket /var/run/php5-fpm-tux.sock -pass-header Authorization

  ErrorLog ${APACHE_LOG_DIR}/error.log

  LogLevel warn

  CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

enable new virtual host and restart apache.

a2ensite tux
service apache2 restart

that’s it!

references

quick & dirty

use php-fpm with apache in debian (mod_fastcgi), en, 2013-02-02
Apache2 mpm worker + fastcgi + php5-fpm on debian, en, 2012-11-02
Apache Worker, FastCGI, PHP-FPM and APC, en, 2012-01-29

explaining differences, more in detail

installing apache + mod_fastcgi + php_fpm on …, en, 2011-04-08
PHP-FPM: Mit der Lizenz zum Verwalten, de, 2011-07-20
Apache2, PHP-FPM, FastCGI and APC Opcode Cache, fr, 2010-08-14

some ideas why to go for FastCGI and Opcode Cache

FastCGI with a PHP APC Opcode Cache, en, 2009-07-07