How to cache your website using NGINX and FastCGI in CentOS 7 with PHP FastCGI Process Manager PHP-FPM

How to cache your website using NGINX and FastCGI in CentOS 7 with PHP FastCGI Process Manager PHP-FPM

Among the many good reasons leading more and more Linux System Administrators to migrate from Apache Web Server to Nginx, performance plays a decisive role: not only Nginx is arguably faster, lighter and resource-intensive than Apache, but it also supports a number of different caching methods that greatly outperform its competitor. To be completely honest we ought to say that Apache has mod_cache, which isn’t bad at all… Yet it’s hardly a match – in terms of performances, speed and ad granular control – when compared the top two Nginx caching solutions: FastCGI-Cache and Proxy-Cache.

The main difference between the two is the protocol that they use to communicate with the backend: FastCGI-Cache caches output from a PHP-FastCGI backend, while Proxy-Cache is related to upstreams that use HTTP as the backend protocol. In this post we’ll deal with the former one, leaving the latter from this other article, where we also explainend a bunch of basic concepts regarding HTTP proxy and its benefits in terms of scaling, stability, security and performance.

Introducing FastCGI-Cache

FastCGI-Cache is currently considered the most efficient way to implement a dynamic cache mechanism in front of our web server with Nginx: that web server can be Nginx itself or another web server that Nginx will “proxy” by catching all the incoming requests, routing them to the upstream PHP-FPM server, get the resulting HTTP responses and return them to the caller.

The FastCGI Nginx module has directives for caching dynamic content that are served from the PHP backend, thus eliminating the need for additional page caching solutions like reverse proxies – such as Nginx Proxy-Cache, Varnish, Squid and the likes – or application specific plugins – such as WordPress Total Cache, WP Super Cache and so on: content can also be conditionally excluded from caching based on the request method, URL, cookies, or any other server variable, just like any good cache mechanism available.

Why Use FastCGI?

FastCGI proxying within Nginx is generally used to translate client requests for an application server that does not or should not handle client requests directly. FastCGI is a protocol based on the earlier CGI (which stands for common gateway interface) protocol, which was originally meant to improve performance by not running each request as a separate process. It is used to efficiently interface with a server that processes requests for dynamic content.

One of the main use-cases of FastCGI proxying within Nginx is for PHP processing. Unlike Apache, which can handle PHP processing directly with the use of the mod_php module, Nginx must rely on a separate PHP processor to handle PHP requests. Most often, this processing is handled with php-fpm, a dedicated PHP processor that has been extensively tested to work with Nginx. It’s worth noting that Nginx with FastCGI can be also used with applications using other languages, as long as there’s an accessible component configured to respond to FastCGI requests.

Installing the prerequisites

Now that we’re done with the introductory part, let’s start to install the required software: Nginx itself and PHP 7.1 with the PHP-FPM module and all their respective prerequisites.

Nginx

To install Nginx, type these commands from a terminal:

Answer “Y” to all the questions until the Terminal says that the installation is complete.

Once done, we could start the Nginx service and also have it start automatically on each startup with the following lines:

However, before doing that, we need to perform some changes to the configuration file (see below).

Php 7

When going with FastCGI, using PHP 7.1 is the recommended choice. In order to install it, together with PHP-FPM, type the following commands in Terminal to add the required repositories to the YUM directory:

Then type the following to install all the required modules:

Again, right after the installation process is complete we could start the PHP-FPM service and also have it start automatically on each startup with the following lines:

php-fpm will start listening on port 9000 of the local machine, meaning that we’ll be able to upstream to it using the  loopback url. However, before doing that, we need to perform some changes to the configuration file (see below).

Nginx Configuration File

Here’s a viable general-purpose Nginx configuration file with FastCGI-Cache support. The lines relevant to FastCGI are marked in bold: if you want to change them, be sure to do it wisely – read the Nginx official documentation for the FastCGI Module before doing that.

Notice how we’ve been using the user www here, as it’s often the system account reserved for serving web pages: depending on your given scenario you should replace it with apache, nginx, www-data and so on: just be sure that it will have the permissions to access to the required folders (see below).

FastCGI directives

Here’s an explanation of the Nginx directives we used in the above configuration file to properly configure FastCGI-Cache:

  • fastcgi_pass: The actual directive that passes requests in the current context to the backend. This defines the location where the FastCGI processor can be reached.
  • fastcgi_param: The array directive that can be used to set parameters to values. Most often, this is used in conjunction with Nginx variables to set FastCGI parameters to values specific to the request.
  • fastcgi_split_path_info: This directive defines a regular expression with two captured groups. The first captured group is used as the value for the $fastcgi_script_name variable. The second captured group is used as the value for the $fastcgi_path_info variable. Both of these are often used to correctly parse the request so that the processor knows which pieces of the request are the files to run and which portions are additional information to pass to the script.
  • fastcgi_index: This defines the index file that should be appended to $fastcgi_script_name values that end with a slash (/). This is often useful if the SCRIPT_FILENAME parameter is set to $document_root$fastcgi_script_name and the location block is configured to accept requests with info after the file.
  • fastcgi_intercept_errors: This directive defines whether errors received from the FastCGI server should be handled by Nginx or passed directly to the client.

Also, we’ve used a couple of other common nginx directives frequently used with FastCGI configurations:

  • try_files: We’re going to use this directive to make sure that the requested file exists before passing it to the FastCGI processor (line 99 of the above code). It’s worth nothing that that line won’t work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi: it’s very important to comment tat ine out if we’ve set up php-fpm/php-fcgi on another machine.
  • include: We can optionally use this directive to include common, shared configuration blocks in multiple locations to overcome the nasty issues caused by the odd Nginx inheritance model for array -type directives (see this ServerFault answer for further details).

Opening the Firewall Port(s)

The default CentOS firewall rules does not allow inbound HTTP / HTTPS traffic, hence its necessary to open up some TCP ports for a webserver such as Nginx to accept connections from the outside. How it can be done depends of the firewall that our CentOS machine is actually using: firewalld or iptables.

Firewalld

These are the shell commands to open up Firewalld (assuming that the public zone has been assigned to the WAN network interface):

Iptables

These are the rules to set for Iptables (assuming  that we want to accept traffic coming from the eth0 network interface):

Setting Permissions

Before firing the engines and starting Nginx we need to ensure that the Linux user we’re using for the Web-Server related tasks (wwwapache, nginx, www-data or anyone else), together with its relevant group, will be able to access to the required www, Nginx-Cache and PHP-FPM-Cache folders. Here are the folder that you need to check:

  • Your website(s) path, such as
  • The Nginx cache folder:
  • The Nginx cache folder specific for FastCGI, which is the value of   directive: in our example, is
  • The Nginx temporary folders:  and    (IMPORTANT: you need to set permissions on both of them – see this ServerFault thread).

That’s it for now: is something goes wrong with your configuration, feel free to contact us and we’ll be happy to help you figure out what you did wrong.

Further references

This post is part of a series of articles, tutorials and guides on the NGINX web server & reverse proxy. To read the other posts, click here!
RELATED POSTS

About Ryan

IT Project Manager, Web Interface Architect and Lead Developer for many high-traffic web sites & services hosted in Italy and Europe. Since 2010 it's also a lead designer for many App and games for Android, iOS and Windows Phone mobile devices for a number of italian companies. Microsoft MVP for Development Technologies since 2018.

View all posts by Ryan