Deploying WordPress with NGINX and FastCGI

If your VPS hosting has Apache installed by default, you can disable or remove it like following.

To disable:

chkconfig httpd off
chkconfig --list httpd
httpd           0:off 1:off 2:off 3:off 4:off 5:off 6:off

To remove:

yum groupremove "Web Server"
OR
yum remove httpd


Install Nginx

Adding yum repository

To add nginx yum repository, create a file named /etc/yum.repos.d/nginx.repo and paste the configurations below:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

After that we can install nginx with yum like so:

yum update
yum install nginx
chkconfig nginx on
service nginx start

Open the browser and point to your IP and you’ll see a welcome page like this.

Nginx Welcome Page

Configuration files

  • Default SSL and vhost config directory: /etc/nginx/conf.d/
  • Default document root: /usr/share/nginx/html
  • Default configuration file: /etc/nginx/nginx.conf
  • Default access log: /var/log/nginx/access.log
  • Default error log: /var/log/nginx/error.log

Update file /etc/nginx/nginx.conf and change worker_processes to match your system CPU(s).

Run following command to list the number of CPU:

grep processor /proc/cpuinfo | wc -l

Update this to match the output of above command:

worker_processes  <number_of_cpu>;

Next we need to enable Gzip, so add the following code to the http section:

# enable gzip
gzip on;
gzip_min_length  1100;
gzip_buffers  4 32k;
gzip_types    text/plain application/x-javascript text/xml text/css;
gzip_vary on;
  • gzip on – turns on/off gzip compression
  • gzip_min_length 1100 – the minimum file-size to be compressed
  • gzip_buffers 4 32k – set the buffer size of gzip, 4 32k is good enough for almost everybody
  • gzip_types text/plain application/x-javascript text/xml text/css – specify which file types should be compressed
  • gzip_vary on – enables response header

Save the config file and reload Nginx:

/etc/init.d/nginx reload

Install PHP

Required Packages

  • php
  • php-mysql
  • php-common
  • php-gd
  • php-mbstring
  • php-mcrypt
  • php-devel
  • php-xml
  • php-bcmath

Optional Packages

  • curl
  • libcurl3
  • libcurl3-dev
  • php5-curl
yum install php php-mysql php-common php-gd php-mbstring php-mcrypt php-devel php-xml php-bcmath

Configure Nginx + FastCGI to run WordPress.

Create file /etc/nginx/conf.d/wp_test.conf with this configuration:

server {
    listen       80;
    server_name  localhost;
    root         /var/www/wordpress;
    index        index.php index.html;
    access_log   /var/log/nginx/access.log;
    error_log    /var/log/nginx/error.log;
 
   # unless the request is for a valid file, send to bootstrap
    if (!-e $request_filename)
    {
        rewrite ^(.+)$ /index.php?q=$1 last;
    }
 
    # catch all
    error_page 404 /index.php;
 
    # use fastcgi for all php files
    location ~ \.php$ {
        #try_files       $uri =404;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
 
    # deny access to apache .htaccess files
    location ~ /\.ht
    {
        deny all;
    }
}

We also need a startup script for the PHP FastCGI server. Create file /etc/init.d/phpfcgi with this code:

#!/bin/bash
#
# Startup script for the PHP FastCGI server.
#
# chkconfig: 345 85 15
# description: PHP is an HTML-embedded scripting language
# processname: php
# config: /etc/php.ini
 
# Source function library.
. /etc/rc.d/init.d/functions
 
PHPFCGI="/usr/bin/php-cgi"
FCGIPORT="9000"
FCGIADDR="127.0.0.1"
FCGI_WEB_SERVER_ADDRS="127.0.0.1"
PHP_FCGI_CHILDREN=2
PHP_FCGI_MAX_REQUESTS=1000
ALLOWED_ENV="PATH USER"
PHPUSER=nginx
PIDFILE=/var/run/phpfcgi.pid
 
if [ -z "$PHP_FCGI_CHILDREN" ]; then
  PHP_FCGI_CHILDREN=5
fi
 
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
 
case "$1" in
  start)
        PHPFCGI_START=$"Starting ${NAME} service: "
        echo -n $PHPFCGI_START
 
        # check for $PHPUSER, create if non-existent
        if [ -z "`id -u $PHPUSER 2> /dev/null`" ]; then
            useradd -s /sbin/nologin $PHPUSER
        fi
 
        # clean environment
        E=
        for i in $ALLOWED_ENV; do E="$E $i=${!i}"; done
        daemon --user $PHPUSER --pidfile $PIDFILE "env - $E $PHPFCGI -q -b $FCGIADDR:$FCGIPORT &> /dev/null &"
 
        pid=`pidof php-cgi`
        if [ -n "$pid" ]; then
            echo $pid > $PIDFILE
            success $PHPFCGI_START
        else
            failure $PHPFCGI_START
        fi
        echo
        ;;
  stop)
        echo -n "Stopping php-fcgi: "
        killproc -p $PIDFILE phpfcgi
        echo
        ;;
  status)
        status phpfcgi
        ;;
  restart)
        $0 stop
        $0 start
        ;;
  *)
        echo "Usage: $0 {start|stop|status|restart}"
        exit 1
esac
 
exit 0

Ensure that the init script is executable:

chmod +x /etc/init.d/phpfcgi

Now you should be able to stop, start, and restart PHP with the usual CentOS commands:

chkconfig phpfcgi on
service phpfcgi start

Testing

Create a file /var/www/wordpress/test.php with this code:

<?php
    phpinfo();
?>

Open the browser and point to “http://your-ip/test.php”. You should see the PHP information page.


Install MySQL

yum install mysql-server
chkconfig mysqld on
service mysqld start

Run secure installation script

/usr/bin/mysql_secure_installation

This will give you the option to remove the test databases and anonymous user created by default, and also to create the root password. This is strongly recommended for production servers.

Now you’re ready for WordPress installation 🙂