Install and configure NGINX and Mongrel for Rails

Some times ago i wrote an article about installing a Rails stack on Debian Etch (our production server), then how to configure Apache 2 + fcgid to run our Rails app.

After several tests with this deployment configuration , we encountered some problems of performance (i will detail what our application does in a future article) :

- First with Apache server, after an idle time, then accessing a page of our application, we should wait for a long time before our page loads. Seems fcgid processes take a long time to (re)start.

- In our application, we deliver some files with a download controller : for bigger files, the download was very long.

We decided recently to switch the Apache2 / fcgid configuration to Mongrel (Ruby HTTP server) + nginx (as proxy in front of Mongrel).

I will explain you how to proceed.

We suppose here you have already installed Ruby , Rails, mySQL.

Connect as root and follow these steps :

First stop Apache2 :

#/etc/init.d/apache2 stop

Install Mongrel

# gem install mongrel

# gem install mongrel_cluster

Install nginx:

# aptitude install nginx

Configure what we have installed

We have to setup our server apps to boot when the server starts, and shutdown gracefully when the server reboots.

Concerning nginx, it already did automatically this setup at install:

# ls -l /etc/rc?.d/*nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc0.d/K20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc1.d/K20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc2.d/S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc3.d/S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc4.d/S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc5.d/S20nginx -> ../init.d/nginx
lrwxrwxrwx 1 root root 15 2008-05-05 11:00 /etc/rc6.d/K20nginx -> ../init.d/nginx

As you can see, for runlevels 0, 1 and 6 there is a K at the beginning of the link, for runlevels 2, 3, 4 and 5, there is a S. Those two letters stands for Kill and Start.
On Debian (and Ubuntu), runlevels 2, 3, 4 and 5 are multi-users runlevels.
Runlevel 0 is Halt.
Runlevel 1 is single user mode
Runlevel 6 is reboot

Remove Apache 2 service

By hand you should remove every link /etc/rc.X/*apache2.

Using update-rc.d is as simple as :

# update-rc.d -f apache2 remove

Removing any system startup links for /etc/init.d/apache2 …
/etc/rc0.d/K09apache2
/etc/rc1.d/K09apache2
/etc/rc2.d/S91apache2
/etc/rc3.d/S91apache2
/etc/rc4.d/S91apache2
/etc/rc5.d/S91apache2
/etc/rc6.d/K09apache2

Add Mongrel service for automatic startup/stop

# cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d/mongrel_cluster

Edit /etc/init.d/mongrel_cluster and add the following environment setup:

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local:/usr/local/sbin:/usr/local/bin

# chmod +x /etc/init.d/mongrel_cluster

# update-rc.d mongrel_cluster defaults
Adding system startup for /etc/init.d/mongrel_cluster …
/etc/rc0.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc1.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc6.d/K20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc2.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc3.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc4.d/S20mongrel_cluster -> ../init.d/mongrel_cluster
/etc/rc5.d/S20mongrel_cluster -> ../init.d/mongrel_cluster

But as you can see, the default value is 20 which is pretty different than 91 … a S20 link is started before a S91 and and K91 is kill before K20.

I decided to startup nginx after mongrel, and stop nginx before mongrel. I’ll use 23 for nginx.

First remove nginx symlinks:

# update-rc.d -f nginx remove

Then create symlinks for nginx with custom priorities :

# update-rc.d nginx defaults 23 23
Adding system startup for /etc/init.d/nginx …
/etc/rc0.d/K23nginx -> ../init.d/nginx
/etc/rc1.d/K23nginx -> ../init.d/nginx
/etc/rc6.d/K23nginx -> ../init.d/nginx
/etc/rc2.d/S23nginx -> ../init.d/nginx
/etc/rc3.d/S23nginx -> ../init.d/nginx
/etc/rc4.d/S23nginx -> ../init.d/nginx
/etc/rc5.d/S23nginx -> ../init.d/nginx
Create the folder /etc/mongrel_cluster that our Rails app Mongrel config will live in.

# mkdir /etc/mongrel_cluster

Generate the Rails app Mongrel config file:

# mongrel_rails cluster::configure -e production -p 8001 -N 3 -c /path/to/rails/app -C /path/to/rails/app/config/mongrel_cluster.yml -P /path/to/rails/app/log/mongrel.pid -l /path/to/rails/app/log/mongrel.log –user <user> –group <group> -a 127.0.0.1

Verify the config file (/path/to/rails/app/config/mongrel_cluster.yml)

user: <user>
cwd: /path/to/rails/app
log_file: /path/to/rails/app/log/mongrel.log
port: “8001″
environment: production
group: <group>
address: 127.0.0.1
pid_file: /path/to/rails/app/mongrel.pid
servers: 3

Create a symlink to this file into /etc/mongrel_cluster :

ln -s /path/to/your/rails/app/mongrel_cluster.yml /etc/mongrel_cluster/YOURAPPNAME.yml

Configure nginx

We now need to edit our nginx.conf file found in /etc/nginx/nginx.conf to set it up. Edit the values found in my nginx.conf file and modify it to suit your needs.

Nginx is a powerful UNIX tool.

You have noticed we used here nginx as Reverse-Proxy in front of a Mongrel cluster; if the web-server (Mongrel in our case) cannot handle more load , you can even put nginx before the web-server to use it as web-server to handle requests to static files.

Thanks to nginx flexibility, you can pass any types of requests to web-server server by using location sections (all files, only dynamic content requests or some specific locations in your web-server tree):

location / {
proxy_pass http://mongrel:8000/;
proxy_set_header X-Real-IP $remote_addr;
}

It should be fine now! Reboot your server and test everything is up after startup :

# shutdown -r now
Nota : Another tool to test: Varnish, an high-performance HTTP-accelerator.

Tags: , , , , , ,

Leave a Reply