What is so hard about Rails deployment?
Recently there has been a lot of fuss about the ease of Rails deployment. People made various claims, such as “I’ve deployed PHP, Java, (insert something else here) and Rails. Rails is by far the most painful.” and “Java deployment (with Tomcat) is easier.”
I have no experience with Java deployment. But I have a friend who has worked on several high-end software systems written in J2EE. He says that deploying J2EE apps involves creating a .war file and uploading that to the web container (Tomcat). While uploading is easy, creating the .war file is not, and involves editing tons of XML configuration files.
PHP deployment is easy:
1. Upload files to server.
2. There is no step 2. (assuming we don’t have to setup the database; but that’s app-dependent)
People say Rails deployment is painful, but I really don’t understand what’s so painful about it:
1. Upload files to server.
2. Setup Mongrel (or lighttpd) on a port.
3. Setup your web server to proxy a virtual host’s request to Mongrel/lighttpd.
It has 2 more steps than PHP, but neither steps are hard. (2) can be done with 1 command. (3) is just copy-pasting some configuration snippets and changing the port numbers.
Granted, it took me a while to figure this out. Back in 2005, deployment documentation was quite bad. I expected to be able to integrate Rails into Apache, only to find out that there is no mod_rubyonrails, and that FastCGI on Apache is broken (at least, it was on Fedora 4 with Apache 2). After lots of Googling I eventually settled with lighttpd, and the thing Just Worked(tm). Today, we have tons of books about Rails deployment.
And I agree, this setup is not usable for shared hosts, who hosts many many websites on a server. Keeping the Mongrel instances running will require far too much memory. But I still do not understand why people claim that Rails deployment, in general, is hard.
I’d like to hear from you why exactly you think Rails deployment is painful, or (if applicable) why it is by far the most painful compared to anything else you’ve tried.

James Urquhart said,
January 14, 2008 @ 12:47 pm
I think one of the major issues of Rails development is its comparative bloat compared to other solutions. E.g. when deploying PHP apps, not once did i think “Right, i’ll need to set up a clustering database, a balancing proxy, and grab 4GB of ram just to be on the safe side”.
(Granted, i would have to think about these things when using PHP on a high demand website, but i seem to get the impression that one has to think about these things much earlier with Rails)
Going onto shared hosting, the “lets squeeze everyone onto a single server” model doesn’t work as well with Rails in part due to the aforementioned bloat. And if you consider shared hosting is a large part of the market, and that Rails is the latest hype that everyone wants to use, then shared hosting providers are going to find it much harder to find customers.
So i would say that another factor in this Rails development rant is that shared hosting providers are using it as a scapegoat as their old business model can’t cope with it nearly as well.
Rails and J2EE Deployment at sinopop.net said,
January 14, 2008 @ 2:02 pm
[…] Hongli Lai asks why some think Rails deployment is difficult. First, a disclaimer. I am not a Ruby on Rails expert. I have only used Rails for one small production project. I found both Ruby and Rails quite easy to pick up coming from a J2EE background. What can be done with such a small investment in learning and in time writing code is quite amazing. However, I, like others, found deployment to be surprisingly inconsistent with the rest of the Ruby on Rails experience. […]
August Lilleaas / leethal said,
January 14, 2008 @ 3:08 pm
Keep in mind that deploying PHP when PHP was 3 years old is just as hard as deploying Rails is now. You had to compile it into apache. Very painful stuff. Work is going to be done on mod_ruby, we’ll get there.
Snailrails said,
January 14, 2008 @ 3:21 pm
To a person that lacks any sort of linux or admin experience. Setting up apache to proxy requests to a mongrel cluster
sounds a lot more painful than uploading PHP files via http://FTP.
Given the lack of support by hosting providers its certainly does make this experience _painful_
But once you know how and are using the proper tools for deployment, it couldn’t be easier.
Ikai Lan said,
January 14, 2008 @ 6:12 pm
Your deployment steps only work on very simple sites. Rails does not thread well, and HTTP requests are blocking for Mongrel. While this is not an issue for most instances, larger deployments realize the need to offload processing for things such as image processing or upload processing to background processes - this is a non issue with PHP or J2EE. As a result, we need to create background services in our applications to solve a problem that doesn’t exist in other frameworks/languages, so it’s a few more steps (making sure the background process has finished its tasks, shutting it down, updating code, and restarting). While it doesn’t seem difficult to do, from a project management standpoint, it’s another point of failure and adds to deployment risk. A related issue is with one of the popular search indexing Gems, Ferret - Ferret indexing in acts_as_ferret does NOT work well with more than one Mongrel instance. You MUST disable indexing or run it as a service.
But in the end, it all comes down to the threading issue, which, because of the way a Mongrel Rails stack is architectured, introduces risk. There is virtually no risk in deploying a PHP application; the upload either completed, or didn’t complete. Maybe painful is not the best description. “High risk” is probably a better term. This is part of the reason I’m looking so closely at JRuby - in theory, Glassfish could solve all these problems.
Hongli said,
January 14, 2008 @ 6:36 pm
Ikai, you are correct that Mongrel only handles 1 request at the same time. But you don’t seem to know that that’s what mongrel_cluster is for. Basically, you use mongrel_cluster to run 2 Mongrel instances (or any number of instances you like). This can be setup with literally two commands - step 1: create config file which contains the number of commands and the starting port; step 2: start the instances with a single command.
Then you setup Apache, Lighttpd, or whatever you use, to proxy to those Mongrel instances. Apache/lighttpd will automatically proxy to the instance that isn’t currently busy. This has been the preferred Rails deployment method for a while now.
In addition, you can setup Lighttpd to serve static files directly, instead of letting them go through Mongrel. This is an example of a stock Lighttpd snippet that I use:
NO_PROXY_EXTENSIONS = "\.(png|gif|jpg|css|js|iso|exe|wmv|mpg|avi|rar|zip)$" ... } else $HTTP["host"] =~ "(^|\.)kennissysteem\.com$" { $HTTP["host"] == "beta.kennissysteem.com" { server.document-root = "/home/webapps/kennissysteem/systeem/public" $HTTP["url"] !~ NO_PROXY_EXTENSIONS { proxy.server = ("" => ( ("host" => "127.0.0.1", "port" => 3865), ("host" => "127.0.0.1", "port" => 3866) )) } accesslog.filename = "/home/webapps/kennissysteem/systeem/log/lighttpd.log" } else $HTTP["host"] =~ "" { url.redirect = ( "^/(.*)" => "http://beta.kennissysteem.com/$1" ) accesslog.filename = "/dev/null" }Here you see beta.kennissysteem.com powered by 2 Mongrel instances. Whenever I deploy a new site, I copy & paste this snippet and change a few values.
I have experience with Ferret and acts_as_ferret. In fact my current project uses it. I run the Ferret server. I agree that it’s less than ideal, but why is it a problem? I only had to run one command - it’s fire-and-forget.
The underlying problem is that Ferret stores the index of the filesystem. If there’s a PHP indexing engine that also use the filesystem, I’m pretty sure it would run into similar issues.
I really do not understand why you talk about “risk”. All this stuff seems fairly simple to me.
- How do you count risk?
- It seems like you’re counting “risk” by the number of manual steps. Is that really an accurate way to count risk? Let us take, for example PHP. The number of effective PHP instances is equal to the number of concurrent Apache request handlers. This is setup in your Apache config file. Now suppose that PHP one day decides to force you to enter this number manually, in a seperate configuration option. And that you have to start these PHP instances manually, instead of letting Apache start them automatically for you. This will be just like how mongrel_cluster works. Will PHP’s risk have increased?
- Why do you think JRuby will reduce risk? Is it only because it uses Java, which you already know, or are there other reasons as well?
jason said,
January 14, 2008 @ 10:58 pm
“Right, i’ll need to set up a clustering database, a balancing proxy, and grab 4GB of ram just to be on the safe side”
The difference there is that your Rails app is massively popular, and your PHP one is just used by your grandma.
jason said,
January 14, 2008 @ 11:03 pm
Hongli,
That’s good, but multiple Mongrel’s does not save you from long running processes jamming your responsiveness. Which is what Ikai was hinting at with background image processing.
Out of interest, how does PHP solve this issue? I’d be surprised if it had an automatic queue for long running processes… which is the exact issue…. and even if it did, it would not be ‘painless’ since it would require some level of work to set up
Hongli said,
January 14, 2008 @ 11:17 pm
Jason,
I’m not sure why you think that multiple Mongrel processes won’t help. If you find that your server’s responsiveness is still jammed, just increase the number of Mongrel processes. If you find that your server can’t handle that number of processes, then you have too many visitors.
PHP doesn’t solve it. In fact, PHP really isn’t much different. By default, Apache allocates up to 150 or so request handlers, which can run concurrently. Each request handler can run exactly one PHP script at a time (i.e. process one HTTP request at a time). The PHP script is run inside the Apache process. If you configure Apache to only use 1 request handler, and your PHP script jams for 10 seconds, then your web server will be unresponsive.
Mongrel_cluster is similar. The number of concurrent requests that your clusters can handle is proportional to the number of Mongrel processes in the cluster.
So the difference with PHP is that PHP uses Apache’s number of request handlers, and thus doesn’t require any additional configuration. Mongrel_cluster requires you to manually set the number of processes in the cluster.
Jeremy said,
January 15, 2008 @ 10:05 pm
The issue with Rails apps isn’t deployment, which is simple, but “deployed maintenance”. Keeping an app running in production, monitoring mongrels, worrying about memory leaks, and all the fun that goes along with that. Sure, when you deploy one app, or two apps, no problem, but let’s say you have ten or fifteen or twenty. Let’s say you have hundreds of apps that you need to keep running. Would you rather have one process (Tomcat) or several hundred Mongrels? In PHP, deployed maintenance was an afterthought. I never worried about server config. I didn’t use God, I didn’t use Monit. It wasn’t ever an issue. If Apache is running, your app is running (excluding php-fcgi). Even in Java, sure, a WAR file is hard to create (potentially), and requires editing configuration files, but once you battle for several days trying to keep your app running, you won’t mind doing some (likely scriptable) editing.
Not to sound like I’m bashing Rails, I’ve been using it since early 2005, and have deployed dozens upon dozens of apps with Rails, but the deployment of Rails is really a problem. I’ve supported my self virtually entirely from writing Rails code since late 2005. I’m a big fan.
I don’t think JRuby is ultimately the answer. I hope Rubinius is, but even then someone needs to find a universal way to deploy Rails apps, by dropping a .rba (or whatever) into a directory and having everything “just work”.
Someone needs to step up and rewrite mod_ruby or write a mod_mongrel, or most companies will start deploying to J2EE containers.
Kevin Ansfield said,
January 21, 2008 @ 5:34 pm
Have any of you tried using the Litespeed webserver instead of apache/lighttpd/nginx/etc proxying to mongrel? It’s ruby_lsapi module makes virtual host setup much easier (plus it has a web based administration interface) and doesn’t use mongrel at all. I’ve found the free a lot more stable in low-memory situations than apache 2 with mod_proxy and a mongrel cluster.
赖洪礼的 blog » Rails deployment: wouldn’t it be great if it worked like this? said,
January 27, 2008 @ 11:27 pm
[…] mean by ‘hard’?” I read their posts more carefully. I read the comments. I also asked around on my blog and the Ruby on Rails mailing list. As with most questions in life, there is not a single answer, […]