Serving PHP with FPM (FastCGI) using Nginx on CentOS

Mar 11th, 2015 in  by Michael Cho

Installation steps to start serving any PHP application (eg Wordpress) using FPM on CentOS, together with a sample Nginx config file.

PHP-FPM is an alternative FastCGI implementation which I prefer for keeping resources manageable in a moderate - high traffic site. You can read about some of the advantages and disadvantages elsewhere, this article is a how-to guide for installing and configuration using Nginx on CentOS.

Step 1 - Install PHP with related libraries


$ yum install php php-mysql php-common php-gd php-fpm php-mbstring php-mcrypt php-devel php-xml

 

Step 2 - Start PHP-FPM


$ php-fpm on

And also make sure it starts when your server boots up.


$ chkconfig php-fpm on

 

Step 3 - Install the EPEL repo

Installing alternative repos allows you to install packages not included in the default yum package manager for CentOS.

Two repos which I recommend installing are the EPEL (Extra Packages for Enterprise Linux) and Remi repos. These will ensure you have a more up to date Nginx installation.


$ wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

Verify that the EPEL repo is installed, by checking that you have the following files:


/etc/yum.repos.d/epel.repo
/etc/yum.repos.d/epel-testing.repo
/etc/yum.repos.d/remi.repo

Then you need to enable the Remi repo, by making sure that you have enabled=1 for when editing:


$ sudo nano /etc/yum.repos.d/remi.repo

 

Step 4 - Install Nginx

Now that you have the extra repos installed, install Nginx by running:


$ yum install nginx

 

Step 5 - Configure Nginx

You will also need a Nginx config file for your site. Usually, this would be a new file you create in /etc/nginx/conf.d/my-site.com.conf and looks something like this:


server {
    listen 80 default;
    server_name my-site.com www.my-site.com;
    
    gzip_static on;

    root /var/www/my-site;

    location ^~ /blog {
        root /var/www/my-site/blog;
        index index.php index.html
        try_files $uri $uri/ index.php?q=$uri&$args;

        rewrite ^/blog(.*)$ /blog/index.php?q=$1;

        location ~ \.php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }

        # This block will catch static file requests, such as images, css, js
        # The ?: prefix is a 'non-capturing' mark, meaning we do not require
        # the pattern to be captured into $1 which should help improve performance
        location ~* \.(?:ico|css|js|gif|jpe?g|png|eot|svg|ttf|woff|txt)$ {
                # Some basic cache-control for static files to be sent to the browser
                expires max;
                add_header Pragma public;
                add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }

    }

}

This config file basically serves files from the /var/www/my-site directory for any visitors to my-site.com, *except* if the visitor comes to anything from my-site.com/blog. If this happens, then we ask Nginx to send any PHP files to FastCGI. An exception is made to serve static files (like image, CSS, or javascript files) directly from Nginx.

I usually also like to add an init file so that you can easily start or stop Nginx using commands like sudo /etc/init.d/nginx start and sudo /etc/init.d/nginx stop respectively. You can do this by adding the following file at /etc/init.d/nginx:


#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin. It should be kept in /etc/init.d/nginx
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf
# pidfile:     /usr/local/nginx/logs/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/etc/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/etc/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

Lastly, make sure you setup the correct permissions for the init file, and set Nginx to start when your server starts.


$ sudo chmod a+x /etc/init.d/nginx
$ sudo /etc/init.d/nginx start
$ chkconfig nginx on

And that's it, your PHP files should now be served via PHP-FPM.


Other articles you may like

Running Metabase locally as a service
May 29th, 2017
Shared filesystem between servers using NFS
Mar 30th, 2017
Create a custom Alexa Skill with AWS Lambda - Part 3 (Lambda)
Dec 18th, 2016
Create a custom Alexa Skill with AWS Lambda - Part 2 (Alexa Skill)
Nov 10th, 2016
Create a custom Alexa Skill with AWS Lambda - Part 1 (Overview)
Nov 1st, 2016