How to set up PHP-FPM together with Apache2 and Froxlor?

This applies to Debian 6 "Squeeze", using PHP 5.4.11 from Dotdeb, and Froxlor 0.9.27 from the Debian archives.

Setup instructions

  1. We assume that your Apache2 server is installed and working, and so is your PHP 5.4.x installation.
  2. Install PHP-FPM:
    apt-get install libapache2-mod-fastcgi php5-fpm
  3. Enable to use PHP-FPM in Froxlor. (After saving, you will get an additional "configuration" link in the line for PHP-FPM.)
  4. In the PHP-FPM configuration in Froxlor, change "Path to php-fpm configurations" to "/etc/php5/fpm/pool.d/", because that's the path where the Debian package expects these .conf files by default. (Alternatively, you could adapt that behavior by editing the include directive in /etc/php5/fpm/php-fpm.conf, at the very bottom).
  5. In the PHP-FPM configuration in Froxlor, change "Command to restart php-fpm" to "/etc/init.d/php5-fpm restart".
  6. Let Froxlor create the new configs:
    php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force
  7. Exchange the php5 handler with the fastcgi one (and other stuff needed by PHP-FPM):
    a2enmod fastcgi actions alias
    a2dismod php5
  8. Fix that Apache complains about a config line "Invalid command 'SuexecUserGroup'" in the Apache vhost configs generated by Froxlor [source]:
    1. apt-get install apache2-suexec
    2. a2enmod suexec
  9. Fix that php-fpm cannot start because Froxlor missed creating system users and groups for the customers it refers to by name in the php-fpm config files.
    1. cd /var/customers/webs/
    2. For every customer in there, execute an equivalent with the proper ID values and customer names for:
      addgroup --gid 10006 customername
      adduser --uid 10006 --gid 10006 customername
  10. Restart PHP-FPM:
    service php5-fpm restart
  11. Restart Apache2:
    service apache2 restart

Should work now. Verify by testing as shown below.

How to test your setup

  1. When testing your setup, test with a domain or subdomain site, not with the "IP and port" site. Because for the latter one, Froxlor misses to create a proper pool configuration file in /etc/php-fpm.d/ (while generating the VirtualHost config file properly), so it will always fail with error messages like this in /var/log/apache2/error.log, using your FQDN server name:

    [Wed Feb 20 19:57:13 2013] [error] [client 91.15.26.18] (2)No such file or directory: FastCGI: failed to connect to server "/var/www/hostname.example.com.fpm.external": connect() failed
    [Wed Feb 20 19:57:13 2013] [error] [client 91.15.26.18] FastCGI: incomplete headers (0 bytes) received from server "/var/www/hostname.example.com.de.fpm.external"

    Note that the file /var/www/hostname.example.com.fpm.external is indeed missing, but that is not the problem: the equivalent file is missing for working websites as well (the docs say "The filename does not have to exist in the local filesystem.").

  2. The first, simplest test is to choose a website and place a little script (called userinfo.php or something) in it with just this content: <?php system('id'); ?>. When calling it in your webbrowser, it should generate output that points to the user and group used in the SuexecUserGroup directive in that site's VirtualHost config. So note that php-fpm, as configured by Froxlor, does not use the script's owner as the user to execute it as, unlike mod_suphp.

  3. Then proceed to test a full website (keeping all other sites temporarily disabled by moving the configs out of /etc/apache2/sites-enabled/). Do not choose a phpMyAdmin or WordPress site for your first testing site however, as there can be special problems to be dealt with.

Fixing other issues

  • "There is no fastcgi wrapper set." When restarting Apache2, you might see messages like "[warn] FastCGI: there is no fastcgi wrapper set, user/group options are ignored". These can be ignored because Froxlor uses suexec to adapt the user and group of the server process, not the php-fpm internal mechanisms. See the system('id'); test above which proves this.
  • Adding directories to open_basedir. When using Froxlor with Apache and mod_php5, you could add site-specific values to open_basedir. When using PHP-FPM, this is no longer possible because site-specific values are now stored in /etc/php5/fpm/pool.d/*.conf files, which will be overwritten when Froxlor regenerates its config files. And there's seemingly no option to add to them from within Froxlor. One might edit the affected .conf files and set them to non-writable for the Froxlor user, but  that will create hard-to-track future problems. It's cleaner to add all directories required for one site to all of them, globally, via "Server -> Settings -> Web Server Settings -> Configuration", where you'll find an option to append paths to the open_basedir setting of all your virtual hosts.
  • Installing Roundcube from the Debian package. You will have to add some paths to the open_basedir default setting as described just above. This includes /etc/roundcube. However, it seems that Froxlor 0.9.27 silently discards any directory in /etc/ that you try to add to open_basedir via "Server -> Settings -> Web Server Settings -> Configuration". Seems to be an undocumented "security feature" 😀 To fix that bug, you could normally overwrite open_basedir per vhost, but PHP-FPM does not interpret that, which is why we have to modify the global open_basedir setting. The best solution I found was to do this (if we're lucky, Debian package management will not complain because we only exchange what is the symlink and what is the real thing):
    rm /var/lib/roundcube/config/*
    mv /etc/roundcube/* /var/lib/roundcube/config/

    ln -s /var/lib/roundcube/config/ roundcube
  • Restarting PHP-FPM. This can be required after doing manual changes to its config files in /etc/php-fpm.d/. The simplest way is: service php5-fpm restart.
  • Enabling the IP-and-port site. By default, Froxlor will not generate a /etc/php5/fpm/pool.d/*.conf file for the "IP and port" website, so it will not be served by php-fpm, resulting in "Server Error 500". This behavior is controlled by the option in Froxlor to use PHP-FPM "for Froxlor itself" (wuite a misnomer, but true: in the "IP and port" site configuration there is the same assumption that Froxlor is normlly provided via that site, where it says "User defined docroot (empty = point to froxlor)"). So the solution goes like this:
    1. Enable that option to use PHP-FPM for Froxlor itself.
    2. Note that the additional options on the same page, to change the user and group names to be used for the Froxlor chost with PHP-NPM, have no effect on the generated VirtualHost config (which seems to be a Froxlor bug). So better leave them as they are at "froxlorlocal".
    3. Let Froxlor recreate the config files:
      php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force
    4. Ensure that there is now a config file in /etc/php5/fpm/pool.d/ named by the FQDN of your host.
    5. Restart Apache2: service apache2 restart
    6. Restart PHP-FPM: service php5-fpm restart
    7. Call up your IP address in your browser and see if it works.
  • Fixing WordPress sites that use URL rewriting. When re-enabling these sites, they will probably fail with this error message in the log: "Request exceeded the limit of 10 internal redirects due to probable configuration error.". The solution is to adapt the .htaccess file of WordPress with the rewrite rules to look like this [source]:
    # BEGIN WordPress
    <IfModule mod_rewrite.c>
    RewriteEngine On
      RewriteBase /
      RewriteCond %{REQUEST_URI} !^/fastcgiphp/*
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . index.php [L]
    </IfModule>
    # END WordPress
  • Fixing Indefero sites that use URL rewriting. Indefero is a simple, Google Code like, open source code and project hosting software that utilizes git. When trying to serve it via PHP-FPM, it will say "Server Error 500", and in the log "Request exceeded the limit of 10 internal redirects due to probable configuration error.". In analogy to the solution for WordPress above, simply add a RewriteCond %{REQUEST_URI} !^/fastcgiphp/* to its .htaccess file to prevent the circular redirection. The .htaccess will then be:
    Options +FollowSymLinks
    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteCond %{REQUEST_URI} !^/fastcgiphp/*
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^(.*) /index.php/$1
    </IfModule>

Posted

in

,

by

Tags:

Comments

One response to “How to set up PHP-FPM together with Apache2 and Froxlor?”

  1. Chris

    With libnss-mysql there is no need to create users by hand!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.