switch apache from prefork to event in Ubuntu 16, get php 7 working

Solution 1:

ezra-s suggests a good approach but it doesn't include some details that might be confusing for folks who rely on package managers. NOTE: I'm not sure if these steps are exact. If anyone encounters trouble or sees issues then let me know and I'll update this post.

Firstly, as of this writing, Ubuntu's apache2 packages insist on prefork if you want to install PHP. Don't despair, however, because you can still use package installers to install and update PHP and apache2 and still get your configuration working with Apache in event mode using PHP-FPM as recommended by the Apache wiki and described in more detail in High-performance PHP on apache httpd 2.4.x using mod_proxy_fcgi and php-fpm. The basic idea is that apache2 and PHP-FPM communicate via socket rather than PHP running as an Apache module.

1) Remove or disable the Apache PHP module

Because the Ubuntu packages insist on prefork Apache when installing PHP, we have to separate them. I did this by using apt to uninstall libapache2-mod-php7.0 because I no longer need the package:

sudo apt-get remove libapache2-mod-php7.0

Alternatively, you might disable the php7.0 Apache module instead, but this will not remove the apt package from your system, which leaves behind annoying system cruft.

sudo a2dismod php7.0

2) Switch Apache to event mode and enable fcgid

I believe these commands should do the trick:

sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo a2enmod proxy_fcgi

3) Install PHP-FPM

I already have PHP 7 installed with its various modules, so I just install PHP-FPM with this command:

sudo apt-get install php7.0-fpm

4) Edit your VirtualHost configuration to handle PHP files with PHP-FPM:

In my case, I edited the default SSL host, /etc/apache2/sites-available/default-ssl.conf, and added this line right near the top:

ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php/php7.0-fpm.sock|fcgi://localhost/var/www/html/

IMPORTANT This instructs Apache to handle PHP file requests with PHP-FPRM and the the path in this directive (/run/php/php7.0-fpm.sock) must match the path specified by the listen directive in the file /etc/php/7.0/fpm/pool.d/www.conf

5) Restart Apache

sudo service apache2 restart

To check if event mode is enabled, use this command:

sudo apachectl -V

In the output, you should see this:

Server MPM:     event

Try creating a phpinfo page and accessing it in your browser. You should see Server API: FPM/FastCGI in the output.

Solution 2:

Distros offer the "mod_php" method for convenience.

While the most performant way is apache w/event + mod_proxy_fcgi -> php-fpm.

Perhaps they should upgrade with the times but its hard for them when so many frameworks come with .htaccess mod_php configurations in a kind of "plug & play" fashion. At the end, it is the admin the only one responsible to administer and configure their site correctly.

If you are in production I would suggest you use a test server to practice the upgrade and changes.

About the wiki I prefer or would suggest you the "handler" method. https://wiki.apache.org/httpd/PHP-FPM#Proxy_via_handler.

That is, configure php-fpm to have a socket ready and with enough permissions for the Apache user to send requests to it and configure Apache to use it.

A quick example:

# needed modules for reverse proxying to php-fpm
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so


<Virtualhost *:443>
    ServerName whatever.example.com
    #other typical directives here
    <Directory /var/www/php-app>
        <FilesMatch \.php>
            SetHandler "proxy:unix:/path/to/app.sock|fcgi://localhost/"
        <FilesMatch>
    </Directory>
</VirtualHost>

Edit:

With this way it does not matter which PHP version you use because Apache does not care, it will just reverse proxy the appropriate requests to php-fpm.

Also, don't forget to unload mod_php to be able to use mpm_event.

Edit 2:

As per request, you don't need to uninstall mod_php packages from debian/ubuntu, Apache only cares about its configuration, so unloading the module will do.