bye Redskin, zdravstvujte Redstar (NginX tips)
female readers: Warning! geek content!
Lately I started realizing that there is a new breed of system administrators. I used to think they just had a boring job maintaining systems and playing BSD snake. But I've come to realize that there are also Agile Sysadmins, the Agmin. These Agmins are constantly adapting systems for performance and scalability. From trying out weird undocumented software to doing mashups with Amazon S3.
At the moment I'm doing a private project that requires a lot of focus on system operations. I am not the best guy for that I have to admit. I can be organized and disciplined, but not in the required maintaining fashion. A skill that is also required by the Agmin. I'm not an agmin (more about this later, because we really need an agmin for this project).
Anyway, I decided to plug out the big ol' Apache server and decided to switch to the ultra-light and fast HTTP server, NginX. The primary argument is obviously performance, second is the philosophy of less is more.

NginX is a light http server coded by some russians. They often use a communist red star in their logo. English documentation is limited, but as a Ruby-ist, I'm used to that. Most of the useful good documentation in the Ruby community comes from blog posts (human conversation and problem solving). OK let's start.
There are a few things that this article will cover:
- Setting up PHP
- Wordpress fancy URL rewrites
- An alternative for mod_userdir
- Example configuration of php5-fastcgi + rails-userdir hack
First of all, when configuring NginX, you better know regular expressions! (cheat sheet here NginX has a pretty basic configuration syntax (no XML, humans configure it afterall). Things I found particularly useful: rewrite and include).
Setting up PHP
Assuming you have debian, you need the 'php5-cgi' binary (or php4-cgi in case you're slow). We will put this binary in 'fastcgi mode', allowing NginX to execute code on it through sockets:
#!/bin/bash PHPFCGI="/usr/bin/php5-cgi" FCGIPORT="8085" FCGIADDR="127.0.0.1" PHP_FCGI_CHILDREN=4 PHP_FCGI_MAX_REQUESTS=1000 USERID=www-data EX=" $PHPFCGI -b $FCGIADDR:$FCGIPORT" echo $EX nohup env - PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS USERID=$USERID sh -c "$EX" &> /dev/null &
This script is a modified version of this russian's one. You can call this script phpd ;)
To enable PHP to your vhost/docroot use this:
fastcgi_pass 127.0.0.1:8085; fastcgi_index index.php; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
I called it enable_php5, so I can include it in my NginX location directives:
include /etc/nginx/enable_php5;
Wordpress Fancy URL rewrites
To enable urls like: http://digigen.nl/2007/05/07/confabiocom-technology-revealed/ you need some special rules. Basically if the file doesn't exist, pass the entire request to wordpress.
/etc/nginx/enable_wordpress:
# wordpress pretty urls
# http://drupal.org/node/110224
location / {
index index.php;
if (-f $request_filename) {
break;
}
if (-d $request_filename) {
break;
}
rewrite ^(.+)$ /index.php?q=$1 last;
}
An alternative for mod_userdir
In apache you have directory lists by default. I could not find this in NginX so I hacked up a RubyOnRails controller that will handle this:
map.connect 'userdir/:user/:path', :controller => "userdir", :action => 'index', :path => '', :requirements => {:path => /.*/}
Note: users can customize this view by creating ~/www/.home.rhtml or ~/www/.home.css
In your NginX configuration (enable_userdir):
# enable homedirs
location ~ /~(.*) {
rewrite ^/~(.*)$ /userdir/$1 break;
include /etc/nginx/enable_mongrel;
proxy_pass http://127.0.0.1:8001;
}
This is to be added to the Rails routes.rb file. All code for this userdir hack is here. Let me know if/when there is a sane solution for this.
note: AutoIndexModule looks like a sane solution (thanks Drakonen)
Example configuration of php5-fastcgi + rails-userdir hack
server {
server_name digigen.nl www.digigen.nl;
access_log /var/log/nginx/digigen.nl.access.log;
index index.php;
root /www/vhosts/digigen.nl;
include /etc/nginx/enable_userdir;
include /etc/nginx/enable_wordpress;
location ~ \.php$ {
fastcgi_param SCRIPT_NAME /www/vhosts/digigen.nl$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME /www/vhosts/digigen.nl$fastcgi_script_name;
include /etc/nginx/enable_php5;
}
}
I hope this might help some people struggling with the strong taste of Vodka:
/etc/init.d/apache stop /etc/init.d/nginx start # it's ok, the cold war is over
2 Responses to “bye Redskin, zdravstvujte Redstar (NginX tips)”
Sorry, comments are closed for this article.
Nice write up, thanks! Just curious, how are you starting your fcgi processes on boot (i.e. how do you ensure your phpd script is run on system init)? I found an init script for managing php-cgi processes, but I'm curious to see how you've set it up there for yourself.
Hey Chu, Hey, I also found a script to do that but I modified that and fit it to my own needs: How's Singapore these days? Let me pop u an email sometime soon.