Continuing on from my previous post on compiling Nginx with Phusion Passenger, some configuration is now in order.
To give credit where due, I’d like to mention that I found much help on the Slicehost articles and tutorials site and adapted some of their instructions for parts of this post. Thanks Slicehost!
I’m using the root account, so there’ll be no ‘sudo’ command used herein. Adjust your commands accordingly if you don’t do things this way.
As I compiled Nginx from source, this meant that no init script was created as it would have been were I to install Nginx via a Debian package. So one needs to be created.
If you have Nginx running, stop it:
# kill `cat /usr/local/nginx/logs/nginx.pid`
Create the file that will become the init script:
# nano /etc/init.d/nginx
Paste this into /etc/init.d/nginx:
#! /bin/sh
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/usr/local/nginx/logs/$NAME.pid --exec $DAEMON
sleep 1
start-stop-daemon --start --quiet --pidfile \
/usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
--exec $DAEMON
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
exit 1
;;
esac
exit 0
Make the file executable:
# chmod +x /etc/init.d/nginx
Add the script to the default run levels:
# /usr/sbin/update-rc.d -f nginx defaults
Now you should be able to start, stop and restart Nginx just as with any other service:
# /etc/init.d/nginx start
...
# /etc/init.d/nginx stop
...
# /etc/init.d/nginx restart
Make sure you actually use the full path as above, rather than typing something like:
# nginx restart
Because if you type just ‘nginx restart’ from some random directory on your server, you’ll actually be calling the Nginx binary rather than the Nginx init script and things will not work as expected.
The init script will also be called on a reboot, so Nginx will automatically start.
If you’ve used Apache on Debian, you’ll probably remember that it makes use of particular conventions regarding its files and directories. Most notably - and I think this is Debian specific - it makes use of two directories: ‘sites-available’ and ‘sites-enabled’. The ‘sites-available’ directory contains the configuration files for all virtual hosts and you then symlink specific configuration files from ‘sites-available’ to the ‘sites-enabled’ directory in order for those sites to be, well, enabled. If I had installed Nginx via a Debian package, this is the layout I would have ended up with and I like these conventions, so this is what I’m going to mirror for my compiled form source Nginx.
Create the two main folders:
# mkdir /usr/local/nginx/sites-available
...
# mkdir /usr/local/nginx/sites-enabled
Create a backup of the default Nginx config file (just in case):
# cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak
Now edit the original:
nano /usr/local/nginx/conf/nginx.conf
Delete the contents of nginx.conf and paste this in its place:
user www-data;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.15;
include /usr/local/nginx/sites-enabled/*;
}
Save and close the file. Note the line ‘include /usr/local/nginx/sites-enabled/*;’ this is what tells Nginx to look in our ‘/usr/local/nginx/sites-enabled/’ directory for extra configuration files.
We’re next going to create a default virtual host config file:
# nano /usr/local/nginx/sites-available/default
Paste this into the file:
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
So Nginx only looks in ‘/usr/local/nginx/sites-enabled/’ for extra configuration files and our new default virtual host config file is in ‘/usr/local/nginx/sites-available/’, this means we need to now create a symlink from one to the other:
# ln -s /usr/local/nginx/sites-available/default /usr/local/nginx/sites-enabled/default
Restart Nginx and browse to whatever URL is the default for your server and you should get the standard “Welcome to nginx!’ page. If you ever want to disable this default virtual host, just delete the symlink and restart Nginx.
So the above should get you going OK for serving up basic pages with Nginx using virtual hosts. But I’m actually wanting to run Rails apps on top of Nginx. When I compiled Nginx I added in the Phusion Passenger module so now I just have to enable it with the virtual host for a Rails app.
Let’s assume that DNS is all set up and you want to create an Nginx virtual host to run your new Rails app at http://fizzbuzz.com/.
Create the location that will store your website files:
# mkdir /var/www/fizzbuzz.com
Put your Rails app’s files into this new directory. Note that you really can create this directory anywhere and call it whatever you like. I’m just once again roughly following Debian conventions and my own preference here.
Create the virtual host config file:
# nano /usr/local/nginx/sites-available/fizzbuzz.com
Paste this into the file:
server {
listen 80;
server_name www.fizzbuzz.com;
rewrite ^/(.*) http://fizzbuzz.com/$1 permanent;
}
server {
listen 80;
server_name fizzbuzz.com;
root /var/www/fizzbuzz.com/public;
passenger_enabled on;
access_log /var/www/fizzbuzz.com/log/access.log;
error_log /var/www/fizzbuzz.com/log/error.log;
}
Some things to note are that the first server block just rewrites ‘www.fizzbuzz.com’ to ‘fizzbuzz.com’, if you have a desperate need for the ‘www’ then you can switch this around and change the ‘server_name’ in the second server block accordingly.
The second server block sets the public root of the Rails app, enables the Phusion Passenger module for this virtual host and sets the location for a couple of log files. You may also have to manually create these log files to start off with:
# touch /var/www/fizzbuzz.com/log/access.log
...
# touch /var/www/fizzbuzz.com/log/error.log
Create the symlink:
# ln -s /usr/local/nginx/sites-available/fizzbuzz.com /usr/local/nginx/sites-enabled/fizzbuzz.com
Restart Nginx and you should be all set to ride Nginx down the rails.
I haven’t mentioned the use of anything like Capistrano for deployment. I may get around to writing about Capistrano at some point, but it’s not like I really need to, there’s heaps that’s been written on it already and I’m hardly an expert. If you’re looking for a more automated way to deploy a Rails app that’s probably a bit safer (at least for more complex projects) than just uploading to a directory and restarting the web server, then I encourage you to check out Capistrano. Sometimes though, uploading files and restarting the web server is exactly the straight forward process that I want and just using Nginx plus Phusion Passenger makes this easy.