14

Apache was running slow in production. After searching for answers for some time, I finally went to #apache IRC channel and the pros had me check the apache mode with this command:

sudo apachectl -V

and were alarmed to find that Server MPM is prefork. They emphatically said DO NOT USE PREFORK ON A PRODUCTION SERVER. As it turns out, the Ubuntu packages (presumably inherited from Debian?) insist on running apache in prefork mode despite the fact that the recommended method for running PHP with Apache clearly recommends proxy_fcgi and php-fpm, then fcgid and ultimately says you should not use prefork:

Why you shouldn't use mod_php with the prefork mpm anymore

  • mod_php is loaded into every httpd process all the time. Even when httpd is serving static/non php content, that memory is in use.
  • mod_php is not thread safe and forces you to stick with the prefork mpm (multi process, no threads), which is the slowest possible configuration

That page also contains some detail on PHP-FPM but this seems a bit elaborate and unclear and seems to involve a lot of manual configuration. I'm disappointed and surprised Ubuntu 16 has no package option for fastCGI mode or something.

I tried switching apache to event mode using a2enmod and when I tried to fire apache back up, I got an error:

Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP

At any rate, I was wondering if anyone had some minimal, step-by-step instructions to get fastCGI mode running on Ubuntu 16 with PHP 7.0 by relying on the package installers as much as possible. I'm currently looking at a lot of poorly explained, vague instructions and I'm concerned about mucking up my production environment with poor decisions.

Also, someone should add mpm-event as a tag option. That's what the #apache IRC guys recommended.

S. Imp
  • 506
  • 1
  • 3
  • 17
  • That last error is because you switched to event, but are still using mod_php. Disable mod_php and switch to php-fpm and it will go away. And may I recommend nginx? – Michael Hampton Mar 22 '18 at 17:01
  • @MichaelHampton the title should mention PHP. It's not difficult to switch apache to event. It's difficult to switch apache to event AND get php 7 working. – S. Imp Mar 22 '18 at 17:34
  • 1
    @MichaelHampton surely you realize that I am confused about how to "disable mod_php and switch to php-fpm." Is that not the very question I ask in my post? Also, the question is not about nginx, which presents yet another realm of learning. Switching to nginx is not practical for this project because I'm working with a team. – S. Imp Mar 22 '18 at 17:38
  • I didn't mention how to disable Apache modules because you demonstrated that you already know how to do this. As for enabling php-fpm, see the answers to this question, online tutorials, etc. – Michael Hampton Mar 22 '18 at 20:19

2 Answers2

18

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.

JonathanDavidArndt
  • 1,414
  • 3
  • 20
  • 29
S. Imp
  • 506
  • 1
  • 3
  • 17
  • 5
    I suggest do not use ProxyPassMatch , because it will not allow to use .htaccess in directory. Use this instead: SetHandler "proxy:unix:/run/php/php7.0-fpm.sock|fcgi://localhost/" – jmp Feb 28 '19 at 11:39
  • This too is working https://gist.github.com/GAS85/990b46a3a9c2a16c0ece4e48ebce7300 – user5858 May 05 '19 at 07:05
  • What will happen if I dont touch this file unlike you told to do: /etc/apache2/sites-available/default-ssl.conf, ? Mine https&http both working fine – user5858 May 05 '19 at 19:07
  • I followed the answer except for ProxyPassMatch, added the Filesmatch line from @waza123's comment to the top of 000-default.conf and restarted apache2 and everything is working perfectly. Thanks to both of you my little VPS is saving a TON of memory and CPU over mpm_prefork – dw1 Jun 05 '19 at 19:02
  • I didn't have to do the ProxyPass or the file edit with Ubuntu Server 19.10. After step 3 (installing PHP-FPM), I just did `a2enconf /etc/apache2/conf-available/php7.3-fpm.conf; systemctl reload apache` and when I created a phpinfo.php file with ` – ServerChecker May 05 '20 at 02:51
  • note the methods you included here for moving from one module to the other are distro dependant. My solution refers only to httpd configuration itself, so it is agnostic regarding the distro or system you may use. – ezra-s Aug 25 '20 at 12:34
7

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.

JonathanDavidArndt
  • 1,414
  • 3
  • 20
  • 29
ezra-s
  • 2,215
  • 1
  • 7
  • 13
  • thanks for your response. I've been doing a lot of trial and error and this is the approach that seems to be working currently. The actual process is a bit more involved because you have to get apache from prefork to event, uninstall libapache2-mod-php7.0 etc. I hope to formulate a more complete answer here in a bit. – S. Imp Mar 22 '18 at 19:17
  • no need to "uninstall" from the apache httpd standpoint, just unload the module. Same with event/prefork, mpm's are modules too in 2.4, so one unloads prefork and loads event. – ezra-s Mar 22 '18 at 19:21
  • ok so maybe you don't have to uninstall the package, but you do have to disable the php module for apache at the very least -- and I'm concerned about an apt-get upgrade breaking the setup. These details are missing from your answer. I'd be delighted if you'd add them because I'm not especially confident in my ability to get the details straight about what exactly I did. – S. Imp Mar 22 '18 at 19:24
  • Perhaps I assumed them, Apache does not care about debian packages either, just its functional configuration. – ezra-s Mar 22 '18 at 19:26
  • Apache *will* care if an apt package update changes its configuration, which is a problem I encountered at one point. In the spirit of my original post, I'd like to provide detailed instructions for others who rely on the package installers (and updates) as I do. – S. Imp Mar 22 '18 at 19:35