When Heelshousing began, the company I work for had never deployed a Rails app before. We decided after much thought, that RailsMachine would be a good fit for us. Through out they way they’ve been a great service, especially for someone like me who didn’t have a lot of experience setting up and maintaining a server.
But of course like with anything else I decided the “basic” setup needed to be customized. I started by building and installing the nginx server with the Fair Proxy Balancer module, and set up appropriate logrotate and init.d scripts for it.
I then decided, based on numerous recommendations and benchmarks out there, to install the Swiftiply gem and use Evented Mongrel. The is done by installing the gem sudo gem install -y swiftiply and then using env EVENT=1 mongrel_rails instead of just mongrel_rails.
I then needed to pick an image processor for resizing uploaded images, rmagick is of course the obvious and almost “default” choice (particularly at RailsMachine). But I had heard reports about it eating memory and being a performance hog. So I decided to go with FreeImage and the ImageScience Gem instead.
Then of course there’s the almost ubiquitous memcached. How could I forget that! I installed that, the memcache-client gem, and the mem_cache_fragment_store gem. We use memcache for sessions, and fragment caching (partly via the Interlock plugin and partly via the built-in Rails fragment cache).
Lastly, since videos can be uploaded and I didn’t want to force property owners to upload a specific format, or have to support embedding different formats I installed ffmpeg, to convert them all to flash.
We also decided to go with Amazon S3’s service for hosting the image and video uploads, as well as serving as an asset host for our stylesheets, and images. And besides the monumental failure they had the other week it’s been a great success. In case you don’t know it’s really easy to map a sub-domain of your site to S3 by naming the bucket that domain name (in our case “assets.heelshousing.com“), and then setting a CNAMErecord with your DNS that points that sub-domain to the appropriate S3 domain name (in our case “assets.heelshousing.com.s3.amazonaws.com“).
It’s also a good idea when uploading images to S3 to set the EXPIRES and CACHE-CONTROL headers for them. Here’s a sample of the code I use to do that:
AWS::S3::S3Object.store(
key, File.open(path), BUCKET_NAME,
:content_type => content_type,
:expires => Time.now.years_since(10).httpdate,
:cache_control => "max-age=315360000",
:access => :public_read
)
I think that should be self explanatory, but if not: I set the key variable to the name/path I want to use on S3, I set the path variable to the path of the file on the local machine, I set content_type to the appropriate MIME type, and of course I set the BUCKET_NAME constant to the name of the bucket I’m using.
Overall these choices were meant to hopefully increase speed of response for the user and performance on the server while also allowing everything to scale well as the sites user base grows.
Update:
The title refers to how Rails apps should not be hosted in shared environments.
Tags: Ruby, Rails, nginx, webdev, server, mongrel, Rails Machine, memcached, Evented Mongrel, Amazon S3