Building a Rails development server
An server stack to facilitate development against almost any Rails environment.
At pebble.code where I work we have a Ubuntu 10.04 LTS server for our Rails and Ruby projects. We use this mostly internally but sometimes expose sites outside of our network to allow clients to quickly review work. When we started the business we built the Rails stack using the standard tools - Apache and Passenger. As our client list grew and we took on a couple of legacy projects we found that this stack no longer matched the environments that we were deploying too and didn’t give us the flexibility we wanted. So here’s how we changed it.
Promoting nginx to port 80 ¶
Nginx is quite simply an awesome web server. It is simple to configure, the memory footprint is small and it can be used to proxy traffic through the web server of our choice and can serve static assets like html, images and css directly before it hits the Rails app.
From having the ability to serve Rails sites only from Apache and Passenger we have moved to this.
We’ve moved Apache to port 81 so if a site needs to be tested on that setup we can still do it. Otherwise we can proxy from nginx directly to Apache. The real flexibility comes from the server we use to serve the Rails app. We deploy by choice on Thin or Unicorn so we can replicate this stack easily. We are looking at Goliath at the moment so we could easily add this in beneath Nginx. We are playing with some other technologies like Node.js too. With Nginx we can support this too.
Getting nginx ¶
If you want to make the switch on Ubuntu there is a PPA repo you can add
sudo -s
nginx=stable # use nginx=development for latest development version
add-apt-repository ppa:nginx/$nginx
apt-get update
apt-get install nginx
If you are currently using Apache you’ll need to decide whether or not to keep it on port 80. We switched Apache to port 81 and promoted Nginx to port 80.
Example configs ¶
The Ubuntu install uses sites-available
and sites-enabled
folders to allow
you to create site configs. Here are some examples that you can use to get you
started.
Logs are disabled in these examples. If you want logging just add a path to the log file.
Default proxy settings ¶
To keep your Nginx configs nice and DRY you can add a file to hold common proxy
settings under /etc/nginx/conf.d
called in my case proxy.conf
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
Proxy to Apache ¶
This expects that you have setup an Apache virtual host on port 81.
server {
listen 80;
server_name site1.com;
access_log off;
error_log off;
location / {
proxy_pass http://127.0.0.1:81/;
}
}
Proxy to Thin ¶
upstream thin {
server unix:/var/www/vhosts/site2.com/httpdocs/current/tmp/sockets/thin.0.sock;
}
server {
listen 80;
server_name site2.com;
access_log off;
error_log off;
location / {
proxy_pass http://thin;
}
}
Proxy to Unicorn ¶
upstream unicorn {
server unix:/var/www/vhosts/site3.com/httpdocs/current/tmp/sockets/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name site3.com;
access_log off;
error_log off;
location / {
proxy_pass http://unicorn;
}
}
So which one is best? ¶
Having played a fair bit recently with servers to serve up Rails apps there isn’t a clear answer I’m afraid. I may get round to publishing my rudimentary benchmarks but I’ve found that for low memory deployments Nginx and Thin is a great choice. The response times are excellent and memory usage is much lower than Passenger or Unicorn. Thin doesn’t come with the same in-built load balancing that you get with Unicorn so HAProxy comes in to play here. HAProxy is another piece in the stack though which may put some off.
If memory isn’t an issue then Unicorn behind Nginx is a great choice. The rolling deployments are a great feature, but you also get free load balancing with Unicorn thanks to the power of UNIX.
If you are not interested in memory or tweaking you are probably best with Passenger behind Nginx.
If you are not interested in doing any sys admin work use Heroku, EngineYard or Brightbox.
Conclusion ¶
If you are rolling your own servers and using Apache switch to Nginx!
Tags
Can you help make this article better? You can edit it here and send me a pull request.
See Also
-
Cloud Foundry - a Ruby and Node.js developer's perspective
This week VMware announced Cloud Foundry, their open source PaaS offering. Here's my take. -
Getting email through spam filters from a Rails App
Recently I did some work on ideapi a Rails app that was consistently delivering email to spam folders of major email providers. After the work email is consistently delivered to Gmail, Google Hosted Accounts, Hotmail, Yahoo and AOL Mail. Here are the details on how it was achieved. -
Installing Passenger 3 with RVM and Nginx on OSX
A multi-ruby development environment on Nginx is easier than ever with the release of Passenger 3