Getting things to play nice

Published 2012-11-06 on Farid Zakaria's Blog

The move to Nginx

It's been only one month on my new Linode machine and I've only ever known of Apache as a front end HTTP server. Apache sadly had to get the boot as I was preparing in deploying me and Alex Hortin's new Node.JS version of the site to facilitate downloading songs from HypeMachine.

Node.JS comes with a complete event-driven web server however I needed a front-end server so that I can host multiple sites on my single instance (such as this blog!). Having a blocking HTTP front-end such as Apache proxy requests to Node? Sounds retarded.

The whole appeal of Node.JS is that it's event-driven and non-blocking which hopefully results in really speedy responses. Luckily Nginx (pronounced EngineX) is also an event-driven web server and is a perfect match as a proxy server for a Node.JS application.

Apache is like Microsoft Word, it has a million options but you only need six. Nginx does those six things, and it does five of them 50 times faster than Apache. -- Chris Lea

Virtual Host Config

Here are the virtual host configs I've used for my blog. Setting up PHP fastCGI and wordpress was probably the most difficult aspect of Nginx but hopefully I've done it all correctly.
If you have any suggestions or fixes please let me know!

Wordpress

File /etc/nginx/sites-available/blog.domain.com

server {
#listen 80; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6

root /home/user/public/blog.domain.com/public;
index index.html index.htm index.php;

access_log /home/user/public/blog.domain.com/log/access.log;
error_log /home/user/public/blog.domain.com/log/error.log;
# Make site accessible from http://localhost/
server_name blog.domain.com www.blog.domain.com;

include global/wordpress.conf;
include global/restrictions.conf;
}

File /etc/nginx/global/restrictions.conf

# Global restrictions configuration file.
# Designed to be included in any server {} block.

location = /favicon.ico {
log_not_found off;
access_log off;
}

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /. {
deny all;
}

# Deny access to any files with a .php extension in the uploads directory
# Works in sub-directory installs and also in multisite network
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~* /(?:uploads|files)/.*.php$ {
deny all;
}

File /etc/nginx/global/wordpress.conf

# WordPress single blog rules.
# Designed to be included in any server {} block.

# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
try_files $uri $uri/ /index.php?$args;
}

# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}

# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;

# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ .php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;

fastcgi_split_path_info ^(.+.php)(/.+)$;
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# fastcgi_intercept_errors on;
fastcgi_pass php5-fpm-sock;
}

Special shoutout

I recently received a very nice donation from someone (you know who you are), and I just wanted to give a special shout out and say thanks. Getting donations such as yours is very heart warming and makes me feel like my time spent on some of these projects are well spent and appreciated. <3