Setup Apache 2.4 and Php FPM with mod proxy fcgi on Ubuntu 13.10

By | December 9, 2014

mod_proxy_fcgi

The module mod_proxy_fcgi is a new one and it allows apache to connect to/forward requests to an external fastcgi process manager like php fpm. This allows for a complete separation between the running of php scripts and Apache.

Earlier we had to use modules like mod_fcgid and mod_fastcgi which all had some limitations. Mod_fcgid for example did not properly utilise the process management capability of php-cgi whereas mod_fastcgi is a third party module.

With the arrival of mod_proxy_fcgi Apache finally gets the ability to neatly talk to external fastcgi process managers making it more efficient at the task.

Delegating php requests to external fpm servers greatly reduces the load on web servers like apache resulting into efficient utilisation of machine resources and faster processing.

request page.php --> Apache --> Php FPM service --> Php process executes page.php

Along with all that, php fpm can run opcode caching engines like apc in a very stable manner.

So in this post, our task is to setup apache + php-fpm using the mod_proxy_fcgi connector.

1. Install and Configure Apache

Ubuntu 13.10 already ships with apache 2.4 so all installables are in the repository itself.

Install Apache if not already done

$ sudo apt-get install apache2

Enable mod_proxy_fcgi

$ sudo a2enmod proxy_fcgi
Considering dependency proxy for proxy_fcgi:
Enabling module proxy.
Enabling module proxy_fcgi.
To activate the new configuration, you need to run:
  service apache2 restart

Restart Apache

$ sudo service apache2 restart

Configure virtual hosts

Next task is to configure a vhost to use mod fcgi proxy to communicate with fpm. The vhost configuration files are stored in the following location

/etc/apache2/sites-available

Get inside there any create your new vhost configuration file by copying the 000-default.conf file which comes with apache.

$ cd /etc/apache2/sites-available
$ sudo cp 000-default.conf mysite.conf
$ sudo nano mysite.conf

Now its time to configure the virtualhost. Here is how I configured the file

<VirtualHost *:80>
.....
	ServerName fpm.localhost

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/mysite

.....
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

.....
	#Include conf-available/serve-cgi-bin.conf

	ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/mysite/$1
	
	<Directory "/var/www/mysite">
		Order allow,deny
		Allow from all
		AllowOverride FileInfo All
		# New directive needed in Apache 2.4.3:
		Require all granted
	</Directory>

</VirtualHost>

The important things to note are :

1. ServerName - This is the domain or the subdomain of your vhost. In this example I used fpm.localhost so that when using that sub domain on localhost, php fpm is used.

2. DocumentRoot - This is the root of this vhost from where the web files shall be served.

3. ProxyPassMatch - This is the directive that tells forward all requests for ".php" files to fcgi server at 127.0.0.1:9000. This is where our php fpm process manager would be running. More on this in the next section.
The fcgi url must contain the exact path to the document root. Otherwise it would say "File Not Found" when requesting for files.

ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/mysite/$1

The first parameter is the pattern to match. So all urls that have a ".php" in them followed by an option slash and anything else are matched and the matched part is forwarded to the fcgi server running at 127.0.0.1:9000.

4. Require all granted - After the ProxyPassMatch line we added a section with Require and AllowOverride directives. It is necessary as of Apache 2.4

Save the file and enable it using the a2ensite command which saves the effort to create the symlink in sites-enabled directory.

$ sudo a2ensite mysite
Enabling site mysite.
To activate the new configuration, you need to run:
  service apache2 reload

Now reload apache configuration

$ sudo service apache2 reload
 * Reloading web server apache2

That completes the apache configuration. The other half of the task is to configure php fpm so that it can finally work.

2. Setup Php-FPM (FastCGI Process Manager)

Next thing is to setup php fpm. Install it via synaptic, if not already done so.

$ sudo apt-get install php5-fpm

The configuration files for fpm are located at

/etc/php5/fpm
/etc/php5/fpm$ ls
conf.d  php-fpm.conf  php.ini  pool.d

The pool.d directory contains the configuration file for each fpm pool and php-fpm.conf is the main configuration file. Our only work is to configure a fpm pool that is to be used with apache or the specific virtual host.

The configuration file for a pool is quite large and there are many parameters that can be configured. But in this post we shall be talking about only the important fields that need be set to get fpm up and running

; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[www]

; Per pool prefix
; It only applies on the following directives:
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or /usr) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = enlightened
group = enlightened

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000

; Set listen(2) backlog.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
;listen.backlog = 128

Create a new configuration file by copying the www.conf file. And edit the fields as explained next.

1. The first options is the name of the pool. We named it 'www' over here. Name it to anything you like or after the domain name it is going to be used with. 'yoursite' for example. That way it would be easier to remember.

2. Setup the user and group that this pool will run with. When you are setting up multiple sites/domains/virtualhosts on a server, you would always want to setup separate user accounts and corresponding pool for each of those. This is an essential security measure, so that every pool has privileges of its own user only.

3. Setup the listening socket. This is the socket on which the master fpm process shall listen for incoming requests. This can be a unix socket or a tcp socket. However mod_proxy_fcgi does not yet support unix sockets, so we are limited to tcp sockets.
Over here its port number 9000 on localhost.

Now restart fpm

$ sudo service php5-fpm restart

Now the new fpm pool should take effect. You can see the new pool process in htop for example.

3. Test the setup

Now that both apache and php fpm are configured and setup, its time to test. Get inside the document root directory and create a php file containing a call to phpinfo() function and open it in your browser.
The "Server API" should be reported as "FPM/FastCGI".

Now that apache and php are setup, you may want to install other things like APC, mariadb database, phpmyadmin etc. Move around this site to find how-to guides on those.

Resources

Check out the following links to learn more
https://wiki.apache.org/httpd/PHP-FPM

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

12 Comments

Setup Apache 2.4 and Php FPM with mod proxy fcgi on Ubuntu 13.10
  1. iarsin

    Thank you very much! This is the only tutorial I found in hours under the bunch of tutorials describing the process for fastfcgi instead of fpm, and therefore working with the directive

    `
    FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -host 127.0.0.1:9001 -pass-header Authorization`

    Instead with debian 10 and apache2.4 the approach to work with mod-proxy-fcgid, php-fpm and mod-event was the right way to get apache2.4 connected to php-fpm!

    `ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/mysite/$1`
    is the proper replacement for going from fastcgi to fpm in apache2.4
    `FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -host 127.0.0.1:9001 -pass-header Authorization`
    or
    `ProxyPassMatch ^/(.*.php(/.*)?)$ unix:/var/run/php5-fpm.sock|fcgi://127.0.0.1:9000/var/www/mysite`

    A very comprehensive and forward tutorial, thanks again!

  2. Viesturs Knopkens

    I know, that maybe this is not 100% on topic, but is there a way to customize “PHP-FPM” error message “File not found.”? Basically I would like that PHP-FPM would display my “apache” 404 page, not text “File not found.” in case it couldn’t find requested PHP file.

  3. Anton

    Thanks! I get it working on Ubuntu 14.04 but in the apache error log i get a lot of ”

    proxy_fcgi:error ” Error parsing script headers” does anyone know why? Run Drupal 6 and 7 if it matters.

  4. Jonathan Pierce

    This is a really useful guide, thanks a bunch!

    Just a note, in your Apache “” config block, the reason why you need the new directive is because Apache 2.4 doesn’t use the old “Order allow,deny” style of access control. “Require all granted” is the functional equivalent of what you have on the first two lines, which can be safely deleted, since they’re being ignored anyway (unless you’re running mod_access_compat, in which case they’re redundant).

    Also, to be (unnecessarily) nit-picky, explicitly including “FileInfo” in the AllowOverride directive isn’t necessary since you’re including “All”.

  5. David Muir

    Sockets are now supported in Apache 2.4.9

    ProxyPassMatch ^/(.*.php(/.*)?)$ unix:/var/run/php5-fpm.sock|fcgi://127.0.0.1:9000/var/www/mysite

    or if you’re using a chroot:

    ProxyPassMatch ^/(.*.php(/.*)?)$ unix:/var/run/php5-fpm.sock|fcgi://127.0.0.1:9000

  6. Teippi Viritykset

    Thanks! Finally a working and good instructions! however i cannot get the phpmyadmin to work. Does it need it’s own sites-enabled conf ?

Leave a Reply

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