Home » Random Goodies » CentOS + Nginx + PHP-FPM + Memcached

CentOS + Nginx + PHP-FPM + Memcached

Time for another update. So recently I’ve been benchmarking a lot out of Apache/Nginx/PHP-FPM/FastCGI, and the conclusion I came to was Nginx + PHP-FPM is still the most solid combo. With that being said, let’s get down and dirty 🙂

First some dependencies:

Install Epel & Nginx repositories:
CentOS 5:
32bit Epel - rpm -Uhv http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
64bit Epel - rpm -Uhv http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
Nginx - rpm -Uhv http://nginx.org/packages/centos/5/noarch/RPMS/nginx-release-centos-5-0.el5.ngx.noarch.rpm

CentOS 6:
32bit – rpm -Uhv http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
64bit – rpm -Uhv http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
Nginx – rpm -Uhv http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm

Now some dependencies:
[[email protected] /]# yum install -q -y make bison flex gcc patch autoconf subversion libxml++ libxml2 libxml2-devel bzip2 bzip2-devel bzip2-libs libcurl libcurl-devel libmcrypt libmcrypt-devel libmhash libhash-devel libxslt libxslt-devel libevent libevent-devel libtool libtool-devel libtool-ltdl libtool-ltdl-devel memcached libmemcached pcre-devel pcre mhash-devel curl-devel syck cpan libaio nginx php-fpm

At this point, we should have Nginx and PHP-FPM installed without issues and ready for a vhost to be configured and a FPM pool started. The following is the Vhost I like to use with WordPress:

[email protected] [/etc/nginx/conf.d]# cat gurutek.biz.conf
server {
# Blacklist if not configured.
listen *:80 default_server;
server_name _;
return 444;

server {
# Separate www redirect to avoid useless overhead on PHP
listen *:80;
server_name www.gurutek.biz;
rewrite ^ $scheme://gurutek.biz$request_uri? permanent;

server {
# Configure domain
server_name gurutek.biz;
listen *:80 deferred;

autoindex off;
port_in_redirect off;
server_tokens off;

client_max_body_size 64m;
client_body_buffer_size 2m;

# Location of WordPress in this case
root /var/www/gurutek.biz;
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?q=$uri$args;

# PHP processing
location ~* (^(?!(?:(?!(php|inc)).)*/uploads/).*?(php)) {
try_files $uri = 404;
fastcgi_split_path_info ^(.+.php)(.*)$;
fastcgi_pass unix:/var/run/php-fpm.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_connect_timeout 5;
fastcgi_send_timeout 30;
fastcgi_read_timeout 30;
fastcgi_buffer_size 2M;
fastcgi_buffers 4 2M;
fastcgi_busy_buffers_size 6M;
fastcgi_temp_file_write_size 2M;

# Cache, rewrites and things
expires 86400s;
add_header Pragma public;
add_header Cache-Control “max-age=86400, public, must-revalidate, proxy-revalidate”;
error_page 404 /404.html;
location /404.html {
error_page 403 = 406;
location ~ /(\.|wp-config.php|readme.html|licence.txt|.htaccess|php.ini|UPGRADING|INSTALLATION|installtion.txt) {
return 404;
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
location ~* ^.+\.(css|js)$ {
rewrite ^(.+)\.(\d+)\.(css|js)$ $1.$3 last;
expires 86400s;
add_header Pragma public;
add_header Cache-Control “max-age=86400, public”;
location ~* \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)$ {
expires 86400s;
add_header Pragma public;
add_header Cache-Control “max-age=86400, public”;
[email protected] [/etc/nginx/conf.d]#

Now, time for PHP-FPM:

In /etc/php-fpm.d, open up www.conf and:

– Comment out listen.allowed_clients
– Replace pool name at the top
– set user
– set group
– set listen to: /var/run/php-fpm.socket

Now, you will need to install the memcache module for Memcached to function with PHP. This can be done as:

[email protected] [/etc/nginx/conf.d]# pecl install memcache

Now that we have the module, the daemon itself is configured by default in /etc/sysconfig/memcached (this can be confirmed in /etc/init.d/memcached). We will be using the following configuration which sets a maximum number of connections to 1024, and a max cache size of 512MB. It also has a few tunings in the OPTIONS entry which will temporarily spike context switching after started but show better performance. Depending on available RAM, boost the CACHESIZE it as needed, and remember it’s in MB:

[email protected] [~]# cat /etc/sysconfig/memcached
OPTIONS=”-k -L -t 2″
[email protected] [~]#

Now that we got the settings out of the way, restart the service and start using it:

[email protected] [~]# service memcached restart
Stopping memcached: [ OK ]
Starting memcached: [ OK ]
[email protected] [~]#

Enjoy the performance boost!

  • memcacheq

    Is the memcache something that handles itself mostly in the background or does it require a lot of config?

  • admin

    Memcached options can be found by default in /etc/sysconfig/memcached when installed on CentOS. You can set things such as port, max connections, user it should run under, and cache size (in MB).

    The following is an optimal config, with a max of 512MB, and a few tunings:

    [email protected] [~]# cat /etc/sysconfig/memcached
    OPTIONS=”-k -L -t 2″
    [email protected] [~]#

    The extended options will show a small spike in context switches once started, however those go down fairly quickly and give you better performance. I went ahead and added this into the article as well. Let me know if you have any other questions or suggestions!