codahale.com٭blog

This is my old blog. My current writing is here: codahale.com

Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You

More and more Rails developers are finding out that deploying a Rails application isn’t as simple as upload and rename; Rails apps work best when running all the time, and many Rails programmers are moving from traditional, shared hosts, like Dreamhost, to virtual private servers, like Rimuhosting, which allow them full control (and responsibility) of production servers.

Given this freedom, there are now a huge number of options available for deploying a Rails application, which is rare for such a new technology. So what to use? Apache + FastCGI? Lighttpd + FastCGI? SCGI? Apache 2? Litespeed? Mongrel? In what configuration? So many questions, so few answers. Here’s what I’ve been deleriously happy with, and how to do it yourself: Mongrel, Apache 2.2, and mod_proxy_balancer, using Capistrano to keep everything at your fingertips.

What the hell is Mongrel?

Mongrel is the hot new kid on the block. It’s a hybrid Ruby/C HTTP server designed to be small, fast, and brutally secure. It’s written by Zed Shaw, who is easily one of the most entertaining and delightfully cranky programmers I’ve ever read. (Zed, if you’re ever in the Bay Area, I owe you a pint.) While it’s a general purpose library, Mongrel is shaping up to be an amazing application server for Rails.

Sounds sweet. What’s Apache got to do with it?

Well, horses for courses. Mongrel is awesome at being a tight little application server for Rails, but when it comes to configurability, speed serving static files, and stability, Apache 2.2 beats the pants off Mongrel. But the main reason is that Rails does not play well with concurrency, and unless your code somehow magically gets around this, it will eat flaming death if it tries to do two things at the same time. So just Mongrel by itself would be slow at serving up static content like images, CSS files, etc., and it would necessarily be limited to a single request at a time, unless the main point of your Rails application was to publicly eat flaming death. (”It’s a feature!”)

So we’re going to be using Apache 2.2 as the front-end for Mongrel, which allows us to both serve up static content like it’s going out of style, but also to use a huge wealth of modules, like mod_deflate, which will improve your site’s responsiveness and download time. We’ll run a cluster of Mongrel servers locally, and route requests through Apache’s mod_proxy_balancer, which uses a sophisticated algorithm to make sure all the Mongrel servers feel equally loved.

Why not (Lighty|Pound|Litespeed|A Large Begonia)?

Apache is the heavy-weight in the web server world, and for good reason. It’s stable, fast, extensible, free as in Beery Speech, and all sorts of enterprisey. It’s gotten a bad rap in the Rails world, though, mainly due to its patchy FastCGI performance. It’s true, Apache + FastCGI is a horrible, horrible solution, unless your problem is “how can I waste my time on a dodgy server config?” in which case you shouldn’t be using the Intarweb while drunk. Finally, Apache currently has a great proxy balancer, which is why we’re using it.

This is not to speak ill of other front-end web servers, and you should feel free to use whatever you’re comfortable with. This article, though, is about how to set up what I’ve got set up, because I can vouch for it being awesome. Chip in on the comments if you’ve got a Mongrel band with a different lead singer and let us know how it’s going for you.

Okay, so what do I need?

I’m going to assume you’ve got Apache 2.2, Ruby 1.8.4, Subversion, and whatever database backend you need installed. That all depends on your operating system. Personally, I’ve had a great experience with Fedora Core 5, but I won’t make fun of you if you use Gentoo, Ubuntu, RHEL, Debian, FreeBSD, or whatever. Just make sure you can install and easily maintain your various pieces of software. Also, make sure you’ve got all the various low-level development tools, like a compiler or two, and the development packages for Ruby and such.

Your application has to be using either ActiveRecordStore, SQLSessionStore, or MemCached to keep track of session data. Files are the worst possible way to deal with sessions, and when you have more than one server reading and writing from the same file-based session store it’s gonna blow up big.

You should have a Capistrano script which will at least run the setup tasks correctly. If you need help with that, there are many blog articles and even a full-blown, if slightly outdated, manual on the damn thing.

Finally, none of this is going to work without root access (or an impossibly permissive server), and you’ll just piss off your admins if you try otherwise.

At this point you should have an Apache 2.2 “Welcome to Apache” style installation, and your Rails application should work just fine in WEBrick mode. If that doesn’t work, you’ve got problems which are best dealt with by tech support, IRC vets, or Friends Who Owe You Favors. If you aren’t at that stage yet, bookmark this page and get to work. I’ll wait until you’re ready.

Ready? Go!

1. Install Mongrel & Friends.

Because otherwise, the rest of this how-to is just going to be super awkward:

[server]$ sudo gem install daemons gem_plugin mongrel mongrel_cluster --include-dependencies

This will download, compile, and install Mongrel and its dependencies, daemons, a library which allows Mongrel to curl up at your server’s feet like a good little poochy poozle, and gem_plugin, which allows folks like yourself to write gem-based, module add-ons to Mongrel. It will also install mongrel_cluster, which contains a few tools which make managing a cluster of Mongrel servers easier.

Finally, it installs sendfile. I’ve already said that Mongrel is slow for static content, and it’s true. However, it’s a smart pup (and Zed’s a smart, smart man). In a proxying configuration, Mongrel will use sendfile, if it’s installed, to send Apache a reference to a file instead of reading it from disk and farting it out to Apache over a local HTTP configuration. This allows Mongrel to do the heavy lifting required of man’s best friend–running your Rails application–without getting bogged down in the minutae of CSS files, images, and Javascript files. Long story short: your site is faster. Many people skip installing sendfile, or don’t know about it, and because of this, they usally write Apache+Mongrel off as slow. Sendfile is the secret ingredient which allows Apache+Mongrel to be blazing fast.

I used to advise installing sendfile, but it doesn’t help–Apache serves the static content, so the 20%-or-so boost on static files is never seen–and it can even cause some pretty severe stability issues. So. No sendfile, and if you’ve got it installed, uninstall it, pronto. (This comes straight from Zed, who would know such things.)

Be sure to install at least mongrel_cluster (and thus, Mongrel) on your workstation–deployment via Capistrano will be complicated, otherwise, since you’ll have to reimplement all the code they’ve thoughtfully laid out for you already.

At this point you’re ready to get your Mongrel configuration on.

2. Mongrel: Sit! Lay! Restart!

First, you need to figure out how much memory you’ve got to spare, how much traffic you’re expecting, and how much money you’re willing to expend. An average Mongrel process can use between 15MiB and 40MiB of memory, depending on what your application does, and you need to figure out how many you can stuff into your server without popping it at the seams. Right now I’m running a decently-sized application with Apache, MySQL, and a cluster of three Mongrel servers in a 128MiB virtual private server with a bit of padding on top to keep the lid on. My advice is to start with two or three and build up to it. As you’ll see later, adding more clusters is stupid-easy. For now, we’ll assume that a cluster of three will do nicely.

Configuring the cluster

Pop open a terminal window, amble on over to your Rails project directory on your workstation, and crank out a cluster config file:

[workstation]$ mongrel_rails cluster::configure -e production \\
  -p 8000 \\
  -a 127.0.0.1 \\
  -N 3 \\
  -c /path/to/your/capistrano/setup's/current

This will add a file, mongrel_cluster.yml, to your config directory, which, when run, will launch a cluster of three Mongrel servers, starting on port 8000, listening on the local interface (and not to evil meanies on the internet).

Before we get to using it, however, we’ll need to make one small change for testing purposes. Open up mongrel_cluster.yml, and comment out the line with address: 127.0.0.1 on it (it’s YAML, so just add a hash at the beginning of the line). We’ll add this back in later, but for now we’ll want to make sure our cluster is behaving properly. Add mongrel_cluster.yml to Subversion, and check it in.

Configuring Capistrano

Mongrel_cluster comes with some drop-in replacements for Capistrano’s restart and spinner tasks. Open your deploy.rb and add the following to the top:

require 'mongrel_cluster/recipes'

Now add the following to your deploy.rb settings:

set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"

Make sure you don’t have any old code in your deploy.rb obscuring the dark, shining beauty of mongrel_cluster. Also be sure you add the :mongrel_conf statement after setting :deploy_to. Otherwise, as Jesse Clark notes in the comments below, you’re in for some weirdness.

Configuring the services

Finally, we need to register your Mongrel cluster as a system-level service, which will allow us to make sure it pops back up when your server reboots.

First, open a terminal window in your server’s services script directory. For most of you, this will be /etc/init.d/. Link the mongrel_cluster script from the gem directory to the services directory:

[server]$ sudo ln -s /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.1.3/resources/mongrel_cluster mongrel_cluster
[server]$ sudo chmod +x mongrel_cluster

Those you on Red Hat-based systems should add mongrel_cluster as a recognized service:

[server]$ sudo /sbin/chkconfig --level 345 mongrel_cluster on

If you’re running a Debian flavor, Ben Curtis assures me this works:

[server]$ sudo /usr/sbin/update-rc.d mongrel_cluster defaults

Those of you using otherwise will have to fend for yourselves. (Let me know how!)

Finally, link your mongrel_cluster.yml from your app’s config directory to /etc/mongrel_cluster:

[server]$ sudo mkdir -p /etc/mongrel_cluster
[server]$ sudo ln -s /your/rails/app/config/mongrel_cluster.yml /etc/mongrel_cluster/yourapp.yml

At this point, your server is rarin’ and ready to go.

Testing your cluster

Well, time to deploy, eh? Almost.

Before you begin, make sure your server can access your Subversion repository. Capistrano unfortunately doesn’t allow you to enter a password when Subversion prompts you for one, so go to a temporary directory and check out the entirety of your application. Subversion will remember your passwords once you’ve entered them.

Got your server playing well with Subversion? Then you’re ready to go!

In a loud voice, say something profound and memorable (”That’s one small step for Rails…”), and deploy that bastard:

[workstation]$ cap cold_deploy

This should checkout the latest version of your code, set up all the symlinks and other fun stuff, and finally start the Mongrel cluster. If it doesn’t, try running it with --trace and see what’s going on. Nine times out of ten, it’s some fiddly bit you forgot about in your haste to get this thing up and running.

If all went well (or was fixed after you let the magic smoke out), you should have three web servers running on your server:

  • http://myserver.com:8000
  • http://myserver.com:8001
  • http://myserver.com:8002

Visit each one in your web browser, and make sure everything works. Fix all the problems you see until each works fine.

Closing up the cluster

Once everything is to your satisfaction, open config/mongrel_cluster.yml back up again, and uncomment the address: 127.0.0.1 line. Save and check in your changes, and re-deploy:

[workstation]$ cap deploy

Everything should go smoothly. Make sure the three 800x ports on your web server are no longer accessible–the only public entrance to your web site should be through Apache!

Now your cluster backend is done! Congrats. Go get a beer, or whatever refreshing beverage the grown-ups let you have. Time to get to work on the front-end.

3. Putting The Inukchuk In Apache

First, find out where your Apache config files are. If your distro isn’t a total crazy-pants, it’ll be something like /etc/httpd/ or /etc/apache2. Within that directory should be conf.d, which is where all of your server-specific config files go. We’re going to take a DRY approach to all this, and try to reuse as many bits of our config files as possible, to avoid the all-too-common problems associated with overlapping anything. Now, all files in the conf.d directory which end in .conf will be automatically included. Keep that in mind.

Removing the cruft

Your Apache installation no doubt includes a certain amount of cruft. Some of that you will need to remove immediately, like config files which block what we’re trying to do, and some of it you’ll want to remove later, like modules you don’t need.

In my installation, at least, the ‘Welcome to Fedora Core 5′ page that every URL produced was created by a default file, welcome.conf. It’s in the way, so out it goes:

[server]$ sudo mv welcome.conf welcome.conf.disabled

Let’s lay out the file structure I’ve been using to keep my config files sane:

myapp.common
The common portions of our configuration. Refactoring this out makes it easier to add additional VirtualHosts down the road (e.g., SSL) while still maintaining exactly the same configuration.
myapp.conf
The main entry, tying everything together to produce a working Rails app.
myapp.proxy_cluster.conf
A proxy balancer with which to interface with the Mongrel cluster.
myapp.proxy_frontend.conf
An (optional) HTTP front-end for managing the proxy load balancing configuration on the fly.

Feel free to replace ‘app’ with the actual name of your application.

And now, for the meat.

myapp.common

The common bits of configuration. This links a Directory or VirtualHost with the proxy-balancer, includes the proper mod_rewrite configuration for Rails, adds support for Capistrano’s enable_web and disable_web commands, and enables mod_deflate for most compressible formats.

  ServerName myapp.com
  DocumentRoot /var/rails/myapp.com/current/public

  <Directory "/var/rails/myapp.com/current/public">
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  RewriteEngine On

  # Make sure people go to www.myapp.com, not myapp.com
  RewriteCond %{HTTP_HOST} ^myapp\.com$ [NC]
  RewriteRule ^(.*)$ http://www.myapp.com$1 [R=301,L]
  # Yes, I've read no-www.com, but my site already has much Google-Fu on
  # www.blah.com. Feel free to comment this out.

  # Uncomment for rewrite debugging
  #RewriteLog logs/myapp_rewrite_log
  #RewriteLogLevel 9 

  # Check for maintenance file and redirect all requests
  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]

  # Rewrite index to check for static
  RewriteRule ^/$ /index.html [QSA] 

  # Rewrite to check for Rails cached page
  RewriteRule ^([^.]+)$ $1.html [QSA]

  # Redirect all non-static requests to cluster
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

  # Deflate
  AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \\bMSIE !no-gzip !gzip-only-text/html

  # Uncomment for deflate debugging
  #DeflateFilterNote Input input_info
  #DeflateFilterNote Output output_info
  #DeflateFilterNote Ratio ratio_info
  #LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
  #CustomLog logs/myapp_deflate_log deflate

myapp.conf

This is pretty simple, it just ties the settings in myapp.common to a VirtualHost on port 80.

<VirtualHost *:80>
  Include /etc/httpd/conf.d/myapp.common

  ErrorLog logs/myapp_errors_log
  CustomLog logs/myapp_log combined
</VirtualHost>

myapp.proxy_cluster.conf

This is loaded by Apache to configure a mod_proxy_balancer cluster mapped to the internal Mongrel servers.

<Proxy balancer://mongrel_cluster>
  BalancerMember http://127.0.0.1:8000
  BalancerMember http://127.0.0.1:8001
  BalancerMember http://127.0.0.1:8002
</Proxy>

myapp.proxy_frontend.conf

This provides a front-end for the proxy load balancing, which you can access from inside your server at http://localhost:8080.

Listen 8080
<VirtualHost *:8080>
  <Location />
    SetHandler balancer-manager
    Deny from all
    Allow from localhost
  </Location>
</VirtualHost>

4. Reboot And Go!

Time to kick over httpd and see if everything worked.

[server]$ sudo /sbin/service httpd restart

If all goes well, your web server is now configured as a Mongrel cluster backend to an Apache 2.2/mod_proxy_balancer frontend. You should feel happy.

5. Bonus Round! Secure server!

This one will depend greatly on your distro, but it does contain one super-important tip for getting a TLS/SSL version of your Rails app working in this setup.

Install mod_ssl, if you haven’t already

[server]$ sudo apt-get install mod_ssl

Replace the defaults in /etc/httpd/conf.d

My install added a file, ssl.conf to the conf.d directory. We’ll use this as a starting point, but let’s do it on our own terms:

[server]$ sudo mv ssl.conf ssl.conf.original
[server]$ sudo cp ssl.conf.original myapp.secure.conf

Now open myapp.secure.conf in your favorite editor (vi, right?), and scroll down to the VirtualHost it adds on port 443 (with Fedora Core 5, this was line 81). Inside the VirtualHost, add this:

Include /etc/httpd/conf.d/myapp.common

# This is required to convince Rails (via mod_proxy_balancer) that we're
# actually using HTTPS.
RequestHeader set X_FORWARDED_PROTO 'https'

That last bit is super important, especially if you’re using the ssl_requirements plugin from 37signals (and why wouldn’t you?). Otherwise, the Mongrel servers won’t know if an incoming request came in secure or not, which means you’ll have no way of knowing if you really should be processing that credit card or not.

Configure the certificates

Now, either look up the SSLCertificateFile and SSLCertificateKeyFile entries in myapp.secure.conf and replace those files with your cert and key, respectively, or edit the entries to point to where you have your cert and key stored.

Restart the server and test

[server]$ sudo /sbin/server httpd restart

Now see if that puppy works!

How well does this actually work?

Personally, it’s worked incredibly well. My “banging tin pots together” benchmarking with httperf indicated that where the Apache1.3+FastCGI setup on Dreamhost could handle ~30 reqs/sec before it would start dropping connections, the Apache2.2+Mongrel setup on a 128MiB Rimuhosting VPS can handle ~90 reqs/sec before things get hinky. In addition, the amount of downtime due to lost worker threads or fudged FastCGI connections was nil. The only times the site went down could be directly traced to me cutting first and measuring second.

Apache+Mongrel is shaping up to be the preferred deployment platform for Rails applications. Recently, the official Ruby On Rails site moved to Apache+Mongrel for their blog, wiki, and manuals site, all of which are much more responsive and have much lower downtimes. Rails Machines, an exciting new “rapid application deployment” hosting service for Rails applications, is using Apache+Mongrel for all their services. Rick Olsen, Rails Core member, has been running both his blog and Rails Weenie on ApacheLitespeed+Mongrel recently, and some people like Jonathon Weiss have moved large sites over to this architecture.

The great thing about this deployment architecture is that it leverages one of Rails’ greatest strengths: share-nothing scaling. All you have to do is add more boxes, and Apache+Mongrel makes that as easy as changing your deployment recipe and your myapp.proxy_cluster.conf file, then restarting the services. Your Mongrel clusters can span boxes and networks, making scaling a simple matter of plugging in hardware.

Long story short: it’s golden.

Thanks to…

I cribbed much of the initial Apache configuration and Mongrel ideas from Bradley Taylor’s Fluxura blog, as well as Jonathan Weiss’s article. Any errors I’m willing to acknowledge as my own, but leave a comment if you find something that doesn’t work for you! Finally, thanks to all the commenters with questions, corrections, and thanks. This article wouldn’t be nearly as accurate without you all. Thanks for trying to follow my instructions. ;-)

Enjoy!

261 Responses to “Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You”

  1. Jim Says:

    If I recall Rick is running litespeed on his blog and rails weenie.

  2. Elliot Smith Says:

    Coda, you are a Jedi master. Many thanks for this, most useful.

  3. Ryan Daigle Says:

    And I won’t make fun of you for using Fedora Core :)

    Nice writeup, thanks!

  4. Ben Curtis Says:

    Here’s the line to get Debian to set up the init script:

    sudo /usr/sbin/update-rc.d mongrel_cluster defaults

  5. Bob Says:

    Great article, when I’m ready to start experimenting I will be back…

    Typo in the article if you are interested?
    “My advice is to start with two or three and build up to it. As you’ll see later, adding more clusters is stupid-easy. For more, we’ll assume that a cluster of three will do nicely.”

    “For more,” probably should have been “For now,”

  6. steve enzer Says:

    Great article! Just what I was looking for.

    I did notice what appears to be an error, in this section:

    Now add the following to your deploy.rb settings:

    set :mongrel_servers, 3
    set :mongrel_port, 8000
    set :mongrel_environment, ‘production’
    set :mongrel_config, “#{current_path}/config/mongrel_cluster.yml”

    I believe that the last line actually needs to be:

    set :mongrel_conf, “#{cur…

    or at least, using the current version of mongrel_cluster it does

  7. Coda Says:

    Thanks a million, Steve! That bit of duplication always made my teeth itch, but I couldn’t get the config file to load on its own. Conf, not config. Awesome!

  8. How to setup a tight Rails deployment server with Apache and Mongrel Says:

    [...] The unstoppable Coda Hale presents an amazing article about setting up a server with Mongrel, Apache, Capistrano, SSL support, etc. for solidly serving Rails applications. An extremely well written and solid guide. [...]

  9. Bloggitation » links for 2006-06-21 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You (tags: ruby rails sysadmin mongrel) [...]

  10. Jesse Clark Says:

    Thanks for the resource, I found a couple things as I was going through it:

    [workstation]$ mongrel_rails cluster::configure -e production \
    -p 8000 \
    -a 127.0.0.1 \
    -N 3 \
    -C /path/to/your/capistrano/setup’s/current

    with this config command I get Errno::EISDIR.

    Not having read the mongrel documentation (…) it took me a while to (incorrectly) assume that it was trying to write the config file to the path given to -C.

    Much much later, I figured out that instead of giving it the path name to the config file, you might have meant to pass a lower case -c which would cause the mongrel_rails start commands to chdir to your deploy directory before executing which allows all the default paths to function correctly.

    4 hours and one case change later, it was off to the races.

    Another small point is that
    set :mongrel_conf, “#{current_path}/config…
    references current_path which references deploy_to and you’ll get odd results if you try to set mongrel_conf prior to deploy_to.

  11. Coda Says:

    Ack! Sorry about wasting four of your hours, Jesse! That was my left pinky getting a little eager with the shift button. And good point on the :mongrel_conf.

  12. steve enzer Says:

    Coda, now that I’ve installed Apache 2.2 and configured the cluster, all I’m getting is a blank page with ‘It Works’ writ across the top in large type — and I’m a bit at a loss as to what that means (or doesn’t mean), as I’d expect (or hope) to be seeing my app… any idea?

  13. Coda Says:

    Hmmm… that sounds like the default configuration of Apache, which you’ll need to disable, so your own configuration can show up.

    In your conf.d directory, there is probably something like welcome.conf which you’ll need to rename to something like welcome.conf.disabled or somesuch.

    If this isn’t the case, then your distro packagers felt like tossing modularity to the wind, and stuffed that portion of code directly into httpd.conf in the conf directory.

    Failing that, you may want to fall back on the advice of #apache on FreeNode.net.

  14. Cyrus Farajpour Says:

    I’ve spent the past few days setting up a very similar hosting environment and was thinking about making a write up myself. Now I see yours and I must say thank you. Your setup points out flaws I didn’t even think of in my own and encompasses (SSL in particular) more than I would have.

    This is a really kickass article.

    ~smoil

  15. Rails, Mongrel, Apache, Capistrano and You · mornography.de Says:

    [...] Coda Hale schlägt wieder zu: Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You. Eine Rundum-Sorglos-Anleitung zum Aufsetzen einer Rails-Anwendung mit Mongrel und Apache 2.2. Über das wundervolle Capistrano. Boochakayaya! [...]

  16. Jesse Clark Says:

    It would have taken me quite a bit longer to get this far without this guide you have provided. I don’t consider the four hours wasted at all and I’m glad that I could contribute in some small way to your excellent article.

  17. Bradley Tayloy Says:

    Nice writeup! Much of this is now automated using the railsmachine gem which I have released as open source. By default, the paths are configured to work with our server configurations, but you should be able to change the appropriate variables for your server.

    To install:
    “gem install railsmachine”

    Quick start guide:
    https://support.railsmachine.com/index.php?pg=kb.page&id=12

  18. Ben Says:

    Coda,
    Thanks for the great blog and plugins all the time… I checked out Rimuhosting and they look like a good fit for what I do. Are you hosting with them now? If you are tell me what domain your hosting with them and you will get a $15 referring credit.
    Thanks,
    Ben

  19. Coda Says:

    Ben– I am indeed hosting with Rimuhosting, and their service has been flawless. Any and all downtime we’ve experienced with them has been strictly due to Sausagefingers McGunjumper (read: me, pushing buttons when I shouldn’t). If you want to toss me a credit, the domain is gpsgeek.com, but it’ll go to my employer, not me.

  20. Jesse Clark Says:

    FYI mod_proxy_balancer was released with Apache 2.1 which is therefore the minimum apache requirement for this setup.

  21. Le blog » links for 2006-06-22 Says:

    [...] Rails, mongrel and Apache Enfin un tutorial pour installer Rails d’une façon efficace et compatible avec Apache, pour m’éviter d’avoir de multiples serveurs web. Et, finallement, ça ressemble vachement à ce qu’on fait en Java. (tags: development hosting rails ruby server software tutorial web apple) [...]

  22. Andi Says:

    Great post, thanks a lot for summing all this up. I wonder if this virtual hosting with 128MB ram is enough. I’ve been thinking of going virutal too, but was always scared by the low RAM they provide, especially with hungry Apache. Any problems with the size of the RAM? Machine must be swapping all the time….?

  23. Coda Says:

    You know, it’s not doing anything else but running Apache, Mongrel, and MySQL. It’s not the most roomy environment, but we honestly haven’t had any problems with it yet. Smaller sites can probably use two Mongrel processes, which would easily fit in a 96MiB VPS.

  24. JGeiger Says:

    Please be sure to read On Boot Initialization Setup in http://mongrel.rubyforge.org/docs/mongrel_cluster.html as it contains information about copying your config files to where the startup script can find them. You might want to add this information into the post as well.

  25. Coda Says:

    Crap, thanks JGeiger! I knew I forgot to write up a step.

  26. Richard Livsey Says:

    Hi - thanks for the great tutorial. In combination with Ezra’s ‘perfect rails stack’ article (http://www.brainspl.at/rails_stack.html) I nearly have my new dedicated server up and running.

    I installed Apache2 from apt-get and all is good, except it doesn’t seem to include mod_proxy_balancer and I can’t seem to work out where to get it from. Any ideas on how to solve this last step would be greatly appreciated!

    Thanks again.

  27. William Says:

    Coda - thank you. A much needed article. ‘Best arguments I’ve read thus far for the Apache2/Mongrel setup. Looks like I need to rearrage a few things and dig in ASAP. I’ll let you know how it goes.

  28. Richard Livsey Says:

    Ooops - Found out that the apt-get version of apache2 is 2.0 and not 2.2 which is the version which comes with mod_proxy_balancer!

    Nuked the apt-get version and installed 2.2.2 from source and all works superbly now!

    Thanks again for the great article :o)

  29. Dan McCormack Says:

    I set this all up today (I’d previously been running Apache 2.0 + FCGI) and I’m loving it. I ran into a problem though. My Rails app lives in a subdirectory of my site, so for example my ProxyPass lines look something like this:

    ProxyPass /test/ balancer://mongrel_cluster/
    ProxyPassReverse /test/ balancer://mongrel_cluster/

    That works, but the paths are all wrong because Rails thinks it’s at the root directory (which, as far as it’s concerned, it is), so it generates links to things like /controller/action instead of /test/controller/action, as it did when I was running it with FCGI. Does anyone have any idea how I might work around this issue? Maybe some clever mod_rewrite rules, or doing something with the routing, or somehow altering Mongrel’s configuration to place the Rails site in a subdirectory to match the Apache config? I’ll be experimenting with a few of these, but if someone has encountered this issue before I’d love to hear how you dealt with it.

  30. Milos Says:

    […] A very accosting layout and a interesting discussion topic, do you provide any Web-based services to universities or students. […] - Sorry for the stupid question :-)

  31. Cyrus Farajpour Says:

    To: Dan McCormack

    I solved this issue by using the reverse_proxy_fix plugin.

    ruby script/plugin install http://svn.napcsweb.com/public/reverse_proxy_fix

    Lemme know if this works for you.

    ~Cyrus

  32. Dan McCormack Says:

    Cyrus: Perfect! With a little modification, that solved my problem exactly. I love the internet. Thanks :)

  33. Charles Brian Quinn Says:

    Kudos, an excellent write-up indeed. Here are my notes/additions:

    in gentoo the startup is:

    $ sudo rc-update add mongrel_cluster default

    and if you symlink (your symlinked) mongrel_cluster config you don’t have to worry about changing that one sitting in /etc/mongrel_cluster:

    $ ln -s /path/to/your/capistranoed/app/current/config/mongrel_cluster.yml /etc/mongrel_cluster/yourapp.yml

    I just got done converting one of our boxen from a lighttpd + externally managed fastcgi over to apache 2.2 mod_proxy_balancer + mongrel_rails on a smokin’ machine. I used siege to load_test her, and will be posting the results soon!

    It would be cool to be able to somehow tell apache’s mod_proxy_balancer how many mongrel_rails exist dynamically — the hacker in me says there’s a way to build up those lines “http://127.0.0.1:8000 …” based on your mongrel_cluster file. Perhaps another day. ;-)

    Thanks a bunch for the great field notes!

  34. Dave Says:

    Hi there,

    Great article!

    I did run into a problem, and I’m not real sure what’s causing this. When I run “rake remote:cold_deply” cap freezes at the following line:

    [192.168.0.200] executing command
    ** [out :: 192.168.0.200] Authentication realm: swaydev
    ** [out :: 192.168.0.200] Password for ‘dave’:
    ** [out :: 192.168.0.200] subversion is asking for a password
    ** [out :: 192.168.0.200] Authentication realm: swaydev
    ** [out :: 192.168.0.200] Username:

    It won’t let me enter a username at this point. Everything just freezes.

    Any ideas?

    Thanks!
    Dave

  35. Dave Says:

    Woops… I meant:

    “rake remote:cold_deploy”

    (forgot the “o”)

    -Dave

  36. Coda Says:

    Dave–that’s a little-known gotcha of Capistrano’s. You need to make sure the account you’re using with Capistrano can access your Subversion repository for each app server of yours. Log into each and svn co your_repos into a temp directory. It’ll prompt you for the username and password, and once you’ve entered it successfully, it’ll remember it. Then you’ll be able to deploy without any problems.

  37. Dave Says:

    Thanks Coda… I can’t believe I missed that!

    -Dave

  38. Doug Says:

    Cluster works for me but not with Apache uhh!
    Using the most basic setup I can think of to get this running. Created a basic rails app structure and configured mongrel. Started mongrel and can access the riding rails page from a browser at http://localhost:8000, http://localhost:8001, etc.

    Problem is when using appache at http://localhost - it loads the riding rails page with no image, and when I click the “About your applictions environment” I get an Apache page: Service unavailable. Checking /etc/httpd/logs/myapp_errors_log shows: Permission denied: proxy: HTTP: attempt to connect to 127.0.0.1:8000 (127.0.0.1) failed

    I’m transitioning (painfully) from a long Windows career to Linux so I’m sure I’m missing something silly here. Any ideas or places for me to look? I’ve checked all the directions in your post about 5 times and can’t find where I went wrong.

    Thanks,
    -Doug

  39. Coda Says:

    Doug–The “About your application’s environment” link will only work for local requests due to security reasons. In the production environment, none of the requests Mongrel receives from Apache will be considered local, and so Mongrel will issue a 403 error: permission denied. This seems like a likely source of your problem. You may want to add a controller to your Rails project and give it a simple index action.

    If that doesn’t work, the problem probably lies in the way you have configured your proxy cluster in Apache. If you email me your config files for that, I’d be able to tell you more.

  40. Jed Hurt Says:

    Hey Coda, I have a Spry VPS with Apache 2.0.46 and I’m too scared to try to upgrade it. Does Apache 2.0.46 have the necessary components to complete this walkthrough?

  41. Coda Says:

    Sorry, Jed. Only people with Apache 2.1 and up can play. You may want to talk to the folks in #apache about the advisability of compling Apache from scratch on your system. It may be easier than you think.

  42. schwuk.com Says:

    Daemonizing Mongrel…

    I did have one minor niggle though. After restarting my server a couple of times during the aforementioned problems I had to restart Mongrel manually. I knew there was a better way to do it, but I didn’t know how. Now I do…

  43. Anonymous Says:

    Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You…

    How to setup a web server, configured as a Mongrel cluster backend to an Apache 2.2/mod_proxy_balancer frontend….

  44. Paul King Says:

    Another thing worth noting is that you should probably configure apache to deny access to the .svn subdirectories. Problem is that I can’t seem to get the information here to work: http://subversion.tigris.org/faq.html#website-auto-update with this configuration.

    Anyone been able to successfully block access to .svn directories, if so where do you put the DirectoryMatch directive?

    Cheers

  45. Michael Says:

    Thanks a lot for this nice writeup, Coda, but there is one thing I don’t seem to get right. You mention that if you install the sendfile gem, mongrel won’t serve any static content but let apache do the work. So far so good, but shouldn’t the following rewrite rule from your myapp.common capture all static requests before mongrel even sees them?

    # Redirect all non-static requests to cluster
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

  46. Michael Says:

    Regarding comment #44: You can set the variable :checkout to “export” in your deploy.rb and capistrano will perform an svn export instead of svn co, so you won’t get a working copy and thus no .svn directories at all on your server.

  47. Coda Says:

    Paul–I’m not sure if it’s the way I’ve got my routes mapped in my application, but my .svn directories aren’t publicly accessible. In terms of having Subversion automatically update things, you’re much better off using Capistrano.

    Michael–two reasons: one, I’m pretty sure it helps with cached content, two, the Apache configuration still lets a few things slide. Regarding the first issue, I’m not positive, and regarding the second, fixing that is on my to-do list, and I’ll update this post when I fix that. In the meantime, it’s a very little bit of extra effort to make the worst-case scenario (Mongrel serving static content) a bit less worst-case.

  48. Chad Westfall Says:

    In regards to Doug’s post on June 27th, 2006 at 4:52pm. I was running into a similar issue:

    (13)Permission denied: proxy: HTTP: attempt to connect to 127.0.0.1:8002 (127.0.0.1) failed

    I found the issue to by SELinux. My dedicated server host setup my box with SELinux enabled and it was causing an issue between mongrel and apache. To disable SELinux temporarily, run the following command:

    setenforce 0

    Conversly, “sentenforce 1″ will enable SELinux again.

  49. Paul Says:

    A minor thing — I believe the phrase is “a bad rap,” not “a bad wrap.”

  50. Jens Says:

    Hi all,

    I would like to use the apache2.2 and the mongrel cluser to serve more than one rails app (the apps run under different VirtualHost configurations). Do I have to create 3 mongrel processes for each VirtualHost entry or can I share (say 6-8 mongrel processes - yep I have enough Ram) between the apps ?

    Thanks a lot
    Great article BTW
    Jens Carroll

  51. Serving Rails with lighttpd, pound and mongrel Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda Hale [...]

  52. Coda Says:

    Paul–Thanks!

    Jens–You can point many vhosts at a single cluster, but a cluster can only run a single application. You’ll need at least one cluster per application.

  53. Michele Says:

    Thanks for the great tutorial!

    A quick note for FreeBSD: Apache 2.2 should be installed with WITH_PROXY_MODULES=yes. i.e. cd /usr/ports/www/apache22 && sudo make WITH_PROXY_MODULES=yes && sudo make install .
    And these modules should be added to the ones added by default in /usr/local/etc/apache22/httpd.conf:
    LoadModule proxy_module libexec/apache22/mod_proxy.so
    LoadModule proxy_balancer_module libexec/apache22/mod_proxy_balancer.so
    LoadModule proxy_ftp_module libexec/apache22/mod_proxy_ftp.so
    LoadModule proxy_http_module libexec/apache22/mod_proxy_http.so
    LoadModule proxy_connect_module libexec/apache22/mod_proxy_connect.so

  54. ian Says:

    One problem I have run into is that my static (cached) pages are correctly served through apache, but my assets like javascripts and css are still served through mongrel.

    I think this has to do with all the requests automatically getting rewritten with a .html suffix ( RewriteRule ^([^.]+)$ $1.html [QSA]).

    I am not enough of a mod_rewrite guru to figure out a solution, but I am sure someone else has.

  55. ian Says:

    To follow up on my previous comment, I have resorted to adding the following lines to my config.

    ProxyPass /images !
    ProxyPass /stylesheets !
    ProxyPass /javascripts !
    ProxyPass /favicon.ico !

    This ensures that my static files get served from apache, and not delegated to mongrel.

    I found this solution on the mongrel mailing list archives.

  56. Coda Says:

    Ian–Thanks a million for that. I was following some of the threads there myself, and I’ve added your suggestions to the article.

  57. Pascal Says:

    Great post Coda! A lot of good ideas. I was able to do an install Mac OS X Tiger (10.4.7) if someone’s interested.

    Works greats so far.

    Here’s the post: http://blog.nanorails.com/articles/2006/07/11/installing-rails-on-mac-os-x-tiger

  58. Installing Rails on Mac OS X Tiger Says:

    [...] If you are only looking for the basics, Locomotive is probably what you need, if you want a grown-up rails setup on Mac OS Tiger, read on. [...]

  59. Seth Says:

    For those of us not yet on Capistrano, but just using a SCM like perforce…what’s the nice way to restart the mongrels after a server push?

  60. Coda Says:

    Seth, you really should take the time to set up Capistrano. It’s maybe 30 minutes of work and cap deploy means never having to say sorry. Also, it works with perforce.

    Besides that, if you’ve registered your Mongrel cluster as a service, the easiest way is to just restart that and let mongrel_cluster do its job.

    On Redhat-ish Linuxes:

    server$ sudo /sbin/service mongrel_cluster stop
    server$ sudo /sbin/service mongrel_cluster start

    On Debian-y Linuxes:

    server$ sudo /etc/init.d/mongrel_cluster stop
    server$ sudo /etc/init.d/mongrel_cluster start

    Or if you haven’t been playing around with services, you can always use mongrel_cluster itself:

    server$ mongrel_rails cluster::stop -C /path/to/your/mongrel_cluster.yml
    server$ mongrel_rails cluster::start -C /path/to/your/mongrel_cluster.yml

    But seriously… Capistrano.

  61. revoluser.com - URLs will save the world Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda Hale Installing and deploying rails… (tags: rails rubyonrails webdev capistrano) Technorati Tags: [...]

  62. Coda Says:

    Finally rolled in some of the advice on mongrel-users to choose the mod_rewrite [P] option over the ProxyPass directives. That way all the static content gets served by Apache, not Mongrel.

    (Took me long enough, jeez.)

  63. Guy Naor Says:

    One small note on deploying using svn.

    My svn servers are all behind tightly controlled firewalls, and the only way to get at them is using ssh+svn using private/public key authentication (yes, I know, I’ve been called paranoid before). In addition, my servers get no access to the internet unless I manually poke a hole in the firewall temporarily - this help prevent downloading things into my machines even if there’s a security breach. This completely precludes using svn for deployment. But all is not lost!

    The way I deploy is I changed the capistrano recipe for checking out the code to do a local export to a temp directory, tar.gz it, and copy it over ssh to the server. Then on the server it is untar.gz’d into the same directory a checkout would put it.

    So all that changes is the update_code recipe, the rest is the same and you get a more secure setup.

  64. Coda Says:

    Guy, you’re paranoid. ;-)

    (Also, you could probably use Subversion over SSL using client certificate authentication, but since you’ve gone to all that trouble… nice hack.)

  65. Chad Says:

    Coda,

    I see you said you “rolled in some of the advice on mongrel-users to choose the mod_rewrite [P] option over the ProxyPass directives” All I can tell is that you removed the ProxyPass directives. I see the following in your myapp.common:

    # Redirect all non-static requests to clusterRewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-fRewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

    So am I to assume that everything else is static and sendfile handles the handoff? How can I see which files are being served by sendfile/apache? The mongrel.log didn’t seem to tell me. Any clarification of how this whole process works would be great!

  66. Le blog » Archive du blog » Début de passage à ligthttpd Says:

    [...] Comme j’ai envie de faire du Ruby chez moi, et que la solution Mongrel+Apache2 m’apparaît comme impossible à mettre en place sur mon Ubuntu, je suis en train de passer doucement à lighttpd et honnêtement, je suis séduit. Séduit par la simplicité apparente de la configuration et ses possibilités avancées (rha, le enhanced virtual hosting, ça m’a l’air génial, ça). Par contre, pour l’intégration de langages de scripts comme le PHP, ça me pose un petit souci, car il faudrait que j’installe PHP indépendament d’Apache, ce qui est difficle quand Synaptic se bloque automatiquement à chaque lancement. Mais ça, c’est un problème propre à la distribution que je travaille à résoudre. Tout ça pour dire quoi ? Simplement que le blog risque de devenir, pour un moment, un intermittent du web et que je m’en excuse. [...]

  67. Doug Johnston Says:

    Holy crap, that’s a great tutorial. I’m ecstatic about my newly constructed Apache 2.2/Mongrel/Capistrano setup. Thanks so much!

  68. Anatol Pomozov’s blog » Blog Archive » Apache, Mongrel and proxy error Says:

    [...] After reading this article I have became electric enough to try it on my current project that recently has gone to beta. [...]

  69. Jason Says:

    Great article. My new CRAM setup works *almost* perfectly. Anyone know why adding basic authentication into the Apache config doesn’t work? I get 404 errors for all static pages and no auth for the rails app.

  70. Hammed Says:

    I just got a VPS account on rimuhosting.com which has Debian Sarge installed which doesn’t have an apt package for apache2.2. Any tips on building it from source with mod_proxy_balancer?

  71. Mongrel Cluster Says:

    [...] I just completed switching over Pecuniarius to use mongrel cluster. It would have probably been easy except that I had Apache 2.0 installed so that meant I needed to upgrade, and naturally I took the long route to do that (build from source numerous times until I got it just right) but I finally got Apache 2.2 with modproxybalance installed and hooked it up to a brand spankin new mongrel cluster following the instructions on Code Hale’s blog (there is no way that’s a real name, but if it is its quite cool). This blog along with symphoniou.us are still running on single mongrel instances, but I’ll fix that soon. [...]

  72. Coda Says:

    Chad–those are indeed the changes. To see who’s serving up what, you can crack open a terminal and type curl -v (the URL) > /dev/null and it’ll print out the headers, which will include the server type. The general process is that Apache checks to see if the file exists on disk (if it doesn’t have a file extension, it assumes it’s .html). If it does, Apache serves it up. Otherwise, the request is proxied to Mongrel.

  73. Coda Says:

    Jason–I’m totally calling this setup CRAM from now on. Sounds much more aggressive than LAMP. No idea about your authentication issues–it works fine for me.

    Hammed–Sorry, haven’t done that. You may want to ask the folks at RimuHosting if you can switch over to Ubuntu, which has 2.2 packaged. Failing that, I’m sure the folks in #apache or #debian would have some decent advice on the matter.

  74. Hammed Says:

    Thanks Coda, I was able to build Apache 2.2 from source - I had assumed it to be more complex than it turned out to be. Later I found instructions for the same in this post on the rimuhosthing forms:

    http://forums.rimuhosting.com/forums/showthread.php?t=230

    I’ve successfullly tested mongrel clusters on the server (yay!) but with capistrano and the same mongrel_cluster.yml, mongrel doesn’t start and complains

    !!! Path to log file not valid: log/mongrel.log

    It appears to be a simlink issue but I haven’t figured it out yet. Any ideas?

  75. Hammed Says:

    guys, make sure to run

    rake remote:setup

    before

    cap cold_deploy

    or you’ll get the !!! Path to log file not valid: log/mongrel.log error I was getting. The shared/log folder is created by the setup task. Duh.

  76. Michael Cho Says:

    guys…i’m a 2-month old newbie to the web-programming world…but Rails been a blast to play with…thou I can’t say for the deployment part (yet)…

    in any case, has anyone bump into this error while doing that “cap deploy” (i have a mongrel_rails restart task in my deploy.rb)?

    ** [out ] ** You have sendfile installed, will use that to serve files.
    ** [out ] !!! PID file log/mongrel.pid does not exist. Not running?
    ** [out ] restart reported an error. Use mongrel_rails restart -h to get help.

    Is that because when I subversion the project I ignored and removed the log files (as per the “HowtoUseRailsWithSubversion” guide)?

    Coda: thanks so much for the post! I’m learning alot going thro the steps! So u’r from Berkeley too? Did you go to that awesome kite festival over the weekend?

    peace folks..

  77. Coda Says:

    Michael–You may want to check out Hammed’s comment right above yours. Either you need to create the log directory, you need to give write permissions on the log directory to the user account that’s running the Mongrel processes, or you’re trying to cap deploy when you should be running cap cold_deploy (or even cap setup).

    (And yeah–I’m in Berkeley. Didn’t go to the kite festival, but I see them occasionally when I ride my bike along the bay to Richmond.)

  78. Armando Says:

    Hey all — great tutorial so far, but I’ve hit a snag. I’m in the “Testing your cluster” section, and when mongrel_cluster tries to start, I get (output from only one of the 3 / it’s repeated 3 times):
    ———————————————————————–
    ** Daemonized, any open files are closed. Look at log/mongrel.8002.pid and log/mongrel.log for info.
    ** Starting Mongrel listening at 127.0.0.1:8002
    ** Starting Rails with production environment …
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel.rb:666:in `register’: undefined method `resolve’ for nil:Mongrel::URIClassifier (NoMethodError)
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel.rb:850:in `uri’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/bin/mongrel_rails:112:in `cloaker_’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel.rb:832:in `listener’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/bin/mongrel_rails:96:in `cloaker_’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel.rb:750:in `initialize’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/bin/mongrel_rails:83:in `run’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel/command.rb:199:in `run’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/bin/mongrel_rails:235
    from /usr/bin/mongrel_rails:18
    ———————————————————————–
    … so, I’m basically unable to continue. Any thoughts?

    - I noticed the comment about not using sendfile, so I’ve removed that
    - mongrel 0.3.13.3
    - mongrel_cluster 0.2.0
    - daemons 0.4.3
    - gem_plugin 0.2.1

    I’ve inspected the code at /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.3/lib/mongrel.rb line 666, and it looks like the classifier member isn’t getting initialized for some reason. :-\

  79. Jon Maddox Says:

    ouch, i just set up my first cluster last night. I’m glad i came back here to reference the post again. Sendfile goes from the secret sauce to a bad influence? yikes…

  80. Armando Says:

    To clear up my comment #78 … I was completely stumped. Then I recompiled ruby, and re-gem-installed all my gems, and then things worked. I had a hard lock-up on my laptop a few weeks ago, so *maybe* some core ruby files got mangled. Otherwise, I have not idea. Anyways, thanks for the tutorial — it was quite helpful.

  81. Otim Says:

    Coda,
    i’ve got the mongrels doing their thing. its great. but apache mucks up the whole things. don’t think i have my virtualhosts right. could you please post a sample config of apache setup using name based virtual hosting?

  82. [post]PostModern » Blog Archive » Dog Days of an Indian Summer Says:

    [...] I’m talking about Capistrano, Rails, Apache, Mongrel. Coda Hale wrote a great article on setting it up. I used his basic procedure, tailored it to my specific needs/personality, and voila! CRAM! [...]

  83. bathow Says:

    Mongrel is the way to go. after struggling with FastCGI and the mysterious hangs, we finally gave up and switched over. Aside from seeing Rails last year as the choice platform, this is the best decision we’ve made on the architecture side.

    now crispynews is humming along beautifully

  84. Ashish Says:

    Hi Coda,

    I am using Apache httpd 2.0.54 on Fedora Core 4.

    I tried to follow your instructions as well as those from various websites.

    However, getting Mongrel to run was a losing battle.

    I tried to upgrade to httpd 2.2.x. I also tried to upgrade my Fedora installation to Fedora Core 5. But only managed to break everything else including Plesk.

    Finally, I am back after a re-imaging of the server back at Fedora Core 4 with httpd 2.0.54.

    Does Mongrel run with Apache 2.0.54?

    If yes, can you please provide me with some help to setup Capistrano and SubVersion?

    Currently I am running Rails using Apache+CGI.

    Regards,

    Ashish.

  85. bryanthompson’s blog » Blog Archive » Apache2, Mongrel, Tiger, and proxy loadhandling install guide Says:

    [...] 3. Install mongrel (via http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/): sudo gem install daemons gem_plugin mongrel mongrel_cluster –include-dependencies [...]

  86. ThinkSplat Blog » Apache + mongrel Says:

    [...] This post is heavily influenced by the Time For A Grown-Up Server web page. I highly recommend you read that web page too for a more in-depth commentary of why you would want to do this. [...]

  87. steve dp Says:

    Awesome stuff man!

  88. Ashish Kulkarni Says:

    Managed to finally get Rails to run with Fedora Core 4, Apache 2.0.54 and SCGI.

    Details of the configuration

  89. Sean O'Hara Says:

    Is there any way to have specific directories point to something other than the mongrel cluster? For instance I have a /stats directory that I would like to maintain access to for web stats. But with the current setup it my Alias in apache for it is ignored. I tried adding ProxyPass /stats ! to my config but it doesn’t work. Any ideas?

  90. Jon Maddox Says:

    Sean, I just resolved that problem today by just using a subdomain. My weblog is powered by mephisto, and i’m using mint for stats. I put mint on a subdomain and they’re living happily with each other.

  91. Cayce Says:

    I’m having a ton of trouble getting my rails app firing. If I run just my mongrel cluster I can see my rails app going to http://10.104.0.121/website/index. I can also see the rolling on rails intro page at http://10.104.0.121.

    However, once I fire up Apache, I still get the rolling on rails intro page, but my app doesn’t fire. I get the following errors in my log:

    [Wed Aug 23 11:03:29 2006] [error] [client 10.70.120.45] no authorization providers configured
    [Wed Aug 23 11:03:29 2006] [error] [client 10.70.120.45] File does not exist: /home/rails/prtrack/public/website

    I don’t have the server dns setup yet, not sure if that has any impact. It just seems that Apache is not routing non-static requests to the cluster the right way.

    I’d really appreciate any help, pointers or guidance in the right direction.
    c.

  92. Cayce Says:

    I have narrowed the problem down to rewrite rules. I have my rails app firing now. I am getting log information on rewrites, so I know that mod_rewrite is operating. It appears, however, that rewrite rules in my railsapp/public/.htaccess file are overriding those in my .conf file(s). Never does the rule invoking the proxy get executed. I have tried setting AllowOverride All/None for various subdirectories in my .conf file to no avail - either the server comes back with “file not found” or it executes the rails app via apache > dispatch.cgi and avoids the mongrel proxy.

    Again, any assistance would be greatly appreciated.

  93. Coda Says:

    Cayce–You can uncomment the rewrite debugging levels in the configs and check the Apache logs for more possibilities. You may also want to check out the #apache channel on Freenode. They’re very helpful.

  94. Cayce Says:

    Turning on those logs is how I figured out what I have to this point. It’s very strange - I can see the various rewrite rules firing in the log file, but it’s only the ones from the rails app public/.htaccess file. It’s just never getting to/firing any of the rewrite rules from my .conf file(s) setup per your article.

    In any event - it’s a problem with rewrite rules on my setup, not anything with your article, which successfully got me almost there. I appreciate the help. I’ll check out the freenode channel.

  95. Cayce Says:

    Just an update - put my app in a sub-folder, used ProxyPass as noted by Dan M. above with Cyrus’ reverse_proxy_fix plug-in and everything is smooth sailing now.

  96. Dave Says:

    I am probably missing something really simple here but I dont really understand what the -c parameter is pointing to in the cluster::configure command:

    [workstation]$ mongrel_rails cluster::configure -e production \
    -p 8000 \
    -a 127.0.0.1 \
    -N 3 \
    -c /path/to/your/capistrano/setup’s/current

    Path to my capistrano setup’s current what?

    What path is that supposed to be pointing to? The path to my deploy.rb?

  97. Dave Says:

    Ohhhhh, I get it… path to my capistrano setup’s “current” folder…

    Sorry, dumb of me

  98. Devin Says:

    During deploy capistrano is unable to locate my executables (svn, mongrel_cluster, etc.). If I use
    set :svn, “/usr/local/subversion/bin/svn”
    in the deploy.rb file it executes the checkout fine, but still can’t find mongrel_cluster. Is there a way to explicitly set the location of your ruby bin directory? Or better yet, anyone know why capistrano is losing the path? The locations are in the path when I log in via ssh with the same user set in deploy.rb. Why aren’t they found by capistrano? I’m still a bit new to linux. Do scripts use a different path then the current user? If so, where can I set it?

  99. Devin Says:

    Just noticed a typo in my comment, mongrel_cluster should be read mongrel_rails.

    if it helps the errors I’m getting from running cap cold_deploy:

    bash: line 2: svn: command not found

    and then when I set :svn, “/usr/local/subversion/bin/svn” to get passed that error I get

    sudo: mongrel_rails: command not found

    again, the commands causing the error run fine when I ssh with the user i’ve set in deploy.rb

  100. Erin Says:

    Hi Code,

    Thanks for the post, it was really helpful.

    I have one small point which is that rewrite only checks for static files before the request is passed to Mongrel. The following code checks for directories as well.


    # Redirect all non-static requests to cluster
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-d
    RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI}

    Erin,

  101. Devin Says:

    Regarding my previous comments (98 & 99):

    I found creating symbolic links for the svn and mongrel_rails executables in /usr/bin works for now. I’d rather not have to do it this way, but it got me up and running so it’s acceptable until I have more time to figure out a better way.

  102. Ben Marini Says:

    Nice article, really crucial information that’s hard to figure out otherwise. Why isn’t this article on Mongrel’s Apache Best Deployment Documetation?? It’s got my vote.

  103. bryanthompson’s blog » Blog Archive » Apache 2.2 + Mongrel on Fedora Core 5 installation guide Says:

    [...] There is a lot more that can be done, especially in the ways of secure your server, blocking off access to the cluster from outside, this will be built upon. Thanks to the excellent Coda Hale guide, as well as Bryan’s guide from here. If you have any comments or suggestions, please leave them here or email kc0dxb@gmail.com [...]

  104. supersonic feet » cPanel + Apache 2.2 + mod_proxy_balancer + mongrel_cluster + hours of frustration = “ahhh, it works” Blog Archive Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You, by Coda Hale. I missed out the Capistrano bit here as I don’t use it yet, but if you do then clicky linky. [...]

  105. Mongrel and Capistrano Says:

    [...] I settled on a pretty clean setup today to make this kind of thing dead simple. I’m assuming you’re already familiar with how to setup mongrel clusters, and that you’ve got the balancer in Apache or whatever forward httpd server figured out and running. [...]

  106. Colin Says:

    Coda,
    I suspect this may be a capistrano problem but maybe not since no one else seems to have ran into this:

    I am trying to do a test deploy where my “server” is the same as my workstation is the same as my svn repository (host = tenfwd.mcmaster.ca). I followed your instructions and everything worked fine up to the “cap cold_deploy” step. Executing this I get:


    * querying latest revision…
    * executing “if [[ ! -d /tmp/cssdb/releases/20060915142450 ]]; then\n svn co -q -r5 http://tenfwd.mcmaster.ca/repos/css /tmp/cssdb/releases/20060915142450 &&\n (test -e /tmp/cssdb/revisions.log || touch /tmp/cssdb/revisions.log && chmod 666 /tmp/cssdb/revisions.log) && echo `date +\”%Y-%m-%d %H:%M:%S\”` $USER 5 20060915142450 >> /tmp/cssdb/revisions.log;\n fi”
    servers: ["tenfwd.mcmaster.ca"]
    Password:
    [tenfwd.mcmaster.ca] executing command
    ** [out :: tenfwd.mcmaster.ca] if: Expression Syntax.
    command finished
    *** [update_code] transaction: rollback

    rake aborted!
    command “if [[ ! -d /tmp/cssdb/releases/20060915142450 ]]; then\\\n svn co -q -r5 http://tenfwd.mcmaster.ca/repos/css /tmp/cssdb/releases/20060915142450 &&\\\n (test -e /tmp/cssdb/revisions.log || touch /tmp/cssdb/revisions.log && chmod 666 /tmp/cssdb/revisions.log) && echo `date +\”%Y-%m-%d %H:%M:%S\”` $USER 5 20060915142450 >> /tmp/cssdb/revisions.log;\\\n fi” failed on tenfwd.mcmaster.ca

    This seems to be telling me there is a syntax error in the “if” command but I have no idea where to find that particular command.

    Help, please!

  107. Colin Says:

    Re: post 106

    Nevermind. After much gnashing of teeth and googling of web found out it was my shell: I use tcsh. Had to create another id that uses bash and add ’set :user, “username”‘ to deploy.rb.

    Thanks for the article.

  108. steve Says:

    There is an issue with mod_rewrite when it finally passes the request along to the balancer…

    If you have any escaped question marks (%3F) in your request, mod_rewrite will unescape them for you, so the balancer then parses what’s after the now-unescaped question mark as a query string (which is what you don’t want). Say for example you goto yoursite.com/users/user_name_with_a_%3F_in_it , that won’t work because rails will only see /users/user_name_with_a_ and the rest will be part of the query string…

    I googled for a while and found a few places mentioning this problem. You can use:

    RewriteMap escape int:escape

    and then use the function ${escape:$some_var} to re-escape the un-escaped URI in your RewriteRule… but I haven’t been able to figure it out yet.

    I tried a lot of things including ${escape:%{REQUEST_URI}} and none of them seemed to work.

    Anyone have any ideas?

    two helpful links:
    http://mail-archives.apache.org/mod_mbox/httpd-users/200510.mbox/%3C8C29B2F93BAE9047A906EF6D6F9C5D439EFD77@exchange2k301.gaia.fr%3E
    http://www.cherrypy.org/wiki/BehindApache

  109. Setting up an Amazon EC2 server with Fedora Core 5 at Notes from a messy desk Says:

    [...] OK, so it’s not a huge step, but we’re all agile around here, aren’t we? Hopefully now you’re comfortable with creating your own AMI and confident with the fact that the new image will boot. The next instalment will involve setting up a reusable Apache, mongrel and rails setup, much like is described in time for a grown up server since that’s pretty much my favourite rails deployment recipe. And we’ll create an AMI for that so that deploying a new rails app, with a little trickery from capistrano, is a turnkey solution. [...]

  110. Setting up an Amazon EC2 server with Fedora Core 5 at Notes from a messy desk Says:

    [...] OK, so it’s not a huge step, but we’re all agile around here, aren’t we? Hopefully now you’re comfortable with creating your own AMI and confident with the fact that the new image will boot. The next instalment will involve setting up a reusable Apache, mongrel and rails setup, much like is described in time for a grown up server since that’s pretty much my favourite rails deployment recipe. And we’ll create an AMI for that so that deploying a new rails app, with a little trickery from capistrano, is a turnkey solution. [...]

  111. leancode.com » Archives » Site Monitoring Shared Host vs Dedicated Says:

    [...] Another related change that happed at the same time: on the shared host I was running the rails app under lighttpd. In setting up the dedicated server, I switched to the hot new thang: apache mod_proxy_cache + mongrel. [...]

  112. Capistrano + Rimuhosting = Super Delicious Says:

    [...] Finally took the plunge to use Capistrano & Rimuhosting. Tried to do this with Dreamhost but it was all fubared beyond repair. Hence the disappearance of this blog as well. Most of you have no doubt read Coda Hale’s excellent write up. [...]

  113. Easy setup a Mongrel cluster with Apache 2.2 on Mac OS X Says:

    [...] Create 4 files for your new application. (adapted from codahale blog) $ sudo touch myapp.common myapp.conf myapp.cluster.conf myapp.yml [...]

  114. Ryan Says:

    Hi am having the save problem as Dave had in post 96 + 97

    I am probably missing something really simple here but I dont really understand what the -c parameter is pointing to in the cluster::configure command:

    [workstation]$ mongrel_rails cluster::configure -e production \
    -p 8000 \
    -a 127.0.0.1 \
    -N 3 \
    -c /path/to/your/capistrano/setup’s/current

    Path to my capistrano setup’s current what?

    What path is that supposed to be pointing to? The path to my deploy.rb?

    . I have set up capistrano according to the agile rails development book (beta) but have no clue what setup folder you are reffering to.

    Thanks!

  115. Paul rogers Says:

    I had problems using web services with this. Here is my thoughts on why, and how to fix:

    When a connection is made, the wsdl contains the address and port to use for future communications( my speculation, I dont know much about webservices)
    if you use 127.0.0.1:8001 as your balancer/proxy url, this is what gets sent on the wsdl. Now thats ip is your client machine, so you get Host actively refused the connection.

    So I think you need to use a server name or the external IP of the machine.

    ie your server is on 192.168.0.1

    use this for your balancer

    BalancerMember http://192.168.0.1:8000
    BalancerMember http://192.168.0.1:8001
    BalancerMember http://192.168.0.1:8002

  116. Jamie Brown Says:

    It takes a little bit of time and effort to learn Capistrano’s functions, but once everything is working and you type in rake deploy for the first time and your application is automatically updated as if by magic, you’ll never be able to do without it again. There’s also a compact one-page Capistrano cheat sheet here that you can download in PDF format which contains all the standard tasks, syntax examples, shell commands and directory structure which is VERY useful.

  117. BigBair Says:

    I am new to the web server business, to make this new phase of my life interesting my company has decided to cut back in my department; To counter this cut back I have hired a ruby developer with the notion that this new sleek fast language will be the answer to my prayers. This adds some new kinks to my life. First I must keep my Microsoft SQL data base so that means my best hope is to keep this all running in windows. That being said I was hoping that you might have some insight to deploy the above mentioned technologies in windows. Thanks for any help you might offer.

    Thanks

    Barry Chapman

  118. Ray Baxter Says:

    For the deflate configuration, I don’t know how or where this is established, but my server gives javascript files the mime type application/x-javascript. It is worth adding that type to the AddOutputFilterByType directive, especially for a Rails application.

    The prototype library is large, but you can reduce it to less than 25% of its uncompressed size. Here is the output from uncommenting the deflate logging.


    "GET /javascripts/prototype.js?1160376830 HTTP/1.1" 12449/55149 (22%)
    "GET /javascripts/effects.js?1160376830 HTTP/1.1" 7197/32871 (21%)
    "GET /javascripts/dragdrop.js?1160376830 HTTP/1.1" 7085/29453 (24%)
    "GET /javascripts/controls.js?1160376830 HTTP/1.1" 7230/28036 (25%)

    While I was at it, I added image/bmp, since the page I was testing had a bitmap on it for some reason.

    Thanks for the really nice and complete walkthrough. I’m running a mogrel cluster, oh yeah.

  119. Brendon Muir Says:

    Hi Coda, I’ve found a couple of problems with this setup, the first one being much more complex than the second! :)

    1) If anyone is using imagemagick_tag to modify any of their images in realtime before displaying them on the page, they’ll get problems with Apache dropping the request for the modified image and calling it 404 without even giving the rewrite rules a go at sorting it out. Here is an example of one of the crude url’s that imagemagick_tag spits out:

    As you can see, i think it’s trying to get around having to set up a custom route by encoding the path characters after the imagemagick method. Mongrel doesn’t mind this, but apache will just balk. Do you know of any way around this? It could affect quite a few people :)

    2) Say your app stores images in a subdir of /public (like file_column does). Everytime you do a remote:deploy it wipes out the files that have been uploaded in the web interface because it’s symlinking a new version of the code (complete with an empty or sparse /public). Again, any thoughts on this problem?

    Cheers,

    Brendon

  120. Boni Says:

    Hello Guys! After setting up everything that was mentioned above my index.html gets rendered properly but when i remove it. I got a 403 error:

    Forbidden

    You don’t have permission to access / on this server.

    Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request.

    Does anybody has any idea why is this?

  121. Ryan Says:

    Hi Everyone,

    Thanks for the great walkthrough. I now have my server up and running, but have a few questions.

    Has anyone been able to get this configuration running with multiple sites (both rails and others?). From my understanding whatever I place in the conf.d folder that has the extension of conf, will be included into the httpd.conf. From what I can see this becomes a problem with the files myapp.proxy_cluster.conf and myapp.proxy_frontend.conf . If i duplicate each of these files, for each virtual host, they will be run outside of the virtual host tag. For example, with the myapp.proxy_cluster.conf file, which points to each of the mongrel servers, if I have 2 clusters of 3 each, appache will hand off to each of the different mongrel clusters randomly, and therefore break the virtual hosting.

    Would it be proper to rename these files, and then include them in the myapp.conf file, like we did with the myapp.common file? Or am I going about this all wrong?

    Thanks Again!

  122. Brendon Muir Says:

    OK, after a week of struggling I’ve found out this important info regarding what Apache does when passing url’s to the cluster.

    Firstly, if for some reason your app encodes slashes in the URL (imagemagick_tag) does this to hide the path to the image that it’s going to manipulate from the rails routing, then you’re stuffed if you use the Apache proxy option. Apache will either say 404 straight away (as encoding slashes is a security problem), or if you add this option to your virtual host: AllowEncodedSlashes On, it will unencode the slashes before it passes it to mongrel so it will still break as your routes won’t know what to do with the strange URL.

    Secondly, Apache will also unencode an encoded + symbol (that is, in imagemagick_tag, when telling it what commands to apply to your image, it links the commands together with plus’s which it then encodes). Unfortunatley either apache or mongrel convert the + to a space, so your commands break.

    To work around all of this I had to:

    Change the way I used imagemagick_tag so that I could embed critical path information to my images in the URL string. I then had to create a special route for this new URL. I used the imagemagick_tag after_filter to then grab the file off the filesystem and output it as a text blob which imagemagick_tag then grabbed and made changes to.

    To work around the + problem, I had to just use one command and then un-DRY the commands in the code by combining them in all the possible combinations that I had used in my views.

    So yea, not an overly perfect solution but it works. I’d be interested to see if anyone else has encountered this kind of thing with apps that don’t quite fit the status quo.

  123. Marc Love Says:

    2) Say your app stores images in a subdir of /public (like file_column does). Everytime you do a remote:deploy it wipes out the files that have been uploaded in the web interface because it’s symlinking a new version of the code (complete with an empty or sparse /public). Again, any thoughts on this problem?

    Brendon, Capistrano creates a folder: “/app_root/shared/system”

    Each time you deploy, the path “/app_root/current/public/system” is symlinked to that folder. So in other words, the system folder in your public folder stays the same from deployment to deployment. This is where you put any cross-deployment files, such as non-interface-related images or documents.

  124. Vlad Jebelev Says:

    There is a typo in your Apache config.

    The following line:
    BrowserMatch bMSIE !no-gzip !gzip-only-text/html

    must be written as
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

    That is there must be a backward slash right before ‘bMSIE’.

    The effect of this typo is that files that are not caught by previously listed rules, such as all *.css and *.js files are never deflated for MSIE users.

  125. Coda Says:

    Thanks, Vlad. It was actually that way from the get-go (and is that way on my servers), but WordPress tends to eat leading slashes instead of, y’know, publishing what I wrote. Thanks for the heads up!

  126. jason Says:

    Hi
    Problem with capistrano starting mongrel. I have the .yml file in [app]/shared/config. However, capistrano tries to start with -C [app]/current/config/mongrel_cluster.yml. This, of course, doesn’t exist, since that folder simply symlinks to latest release.

  127. jason Says:

    Well, I’d been trying to fix for ages, then …
    My error was to create a ‘current’ directory manually. I deleted the whole directory structure redid setup, and heh presto current is a symlink - makes more sense that way!

  128. Conrad Says:

    Hi, I’m trying to get things going on Mac OS X. Thus, I was wondering, what’s the best practice for setting up your local svn repository because Capistrano doesn’t work with file:/// from the documentation?

    Thanks,

    -Conrad

  129. Coda Says:

    Conrad: The server that you’re deploying to must be able to contact the machine on which your SVN repository resides. Your SVN repository appears to be on your workstation, which means that if you’re deploying to another machine, it has to be able to access your workstation. I’d suggest looking into the svn+ssh protocol, which allows Subversion to SSH into your machine and access the repository locally.

  130. My Podium » Blog Archive » links for 2006-10-21 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You (tags: ruby) [...]

  131. Nick Says:

    This is a great post! (but you know this already!)

    I’m getting multiple (11) mysqld processes running and I can’t work out why. I think it would open more but i’m out of memory.

    I’m running apache 2.2. httpd.conf doesn’t say anything about the mysql server configuration. should it?

    I don’t know where/how to configure this. Can anyone help? Thanks

  132. Debian + Ruby on Rails + Mongrel setup « brain dump of an entrepreneur Says:

    [...] http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/ [...]

  133. Tiago Maceddo Says:

    You should also add

    ProxyPreserveHost On

    otherwise certain things such as the endpoint in a wsdl definition (using actionwebservice) will be broken

  134. TheBlatherskite Says:

    Excellent, as usual.

    Chip in on the comments if you’ve got a Mongrel band with a different lead singer and let us know how it’s going for you.

    I’m still playing around with the initial install, but Lighttpd + Mongrel + Pound seems to be working well for me.

  135. Gary Rowe Says:

    Great article Coda - really helped me to get my Rails project off the ground. I’d just like to say that I had real problems getting the reverse_proxy_fix plugin to work for me (being a Rails noob and all). I looked through the comments posted here (thanks everyone) and ended up with the following change to my apache configuration (assuming an application called depot):
    # Send the request (but do not allow access to the dispatcher or the cluster)
    # Note the use of trailing / this allows the mongrel_cluster prefix to work
    ProxyPass /depot/ http://depot_mongrel_cluster:8001/depot/
    ProxyPass /depot http://depot_mongrel_cluster:8001/depot/
    ProxyPassReverse /depot/ http://depot_mongrel_cluster:8001/depot/

    In addition, modifying the mongrel_cluster.yml as follows made everything burst into life:
    prefix: /depot

    Thanks again for the great article!

  136. Robert Says:

    Hi,

    I’m a bit lost with Capistrano here, I followed the instructions word by word but what I get is the following: http://pastebin.ca/277665

    Any idea about what to do?

    Regards,
    Robert

  137. Gitarreninstitut Says:

    Capistrano is very perfect for me and my work^

  138. Coda Says:

    Robert: It looks like you’re passing the update_code task some weird parameters, including :desc.

    This is wrong:

    task :update_code, :desc => "Blah blah" do
    ...

    This is right:

    desc "Blah blah"
    task :update_code do
    ...
  139. John Athayde Says:

    Some bumps I hit that might help others:

    On FreeBSD, I had to change a line in the capistrano gem on my workstation because it was not recognizing [[ as test. I changed line 34 to

    if test ! -d #{configuration.release_path} ; then

    Also, ensure that your user is part of the wheel group and wheel is allowed in the sudoers file in /usr/local/etc/sudoers

    Thanks very much!

  140. Le blog du Libre Accès » Archive du blog » Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda Hale Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda Hale [...]

  141. Mohammad Ali Says:

    it might be a little off-topic but does any one knows of a benchmarking tool for comparing efficency of differrent combo’s?????

    I can off course see the response times in firefox’s fasterfox to compare individual loads to check on mongrel+Apache(thanks to this article) and the lightpd+FastCGI(previous) combo, but that’s too simplistic & leaves lot of questions unanswered.

  142. Rubyrobot Says:

    If your server’s linux distro doesn’t feature the required Apache version for makin a Mongrel cluster, have a look at http://www.rubyrobot.org/article/mongrel-apache-load-balancing-ruby-on-rails for instructions on building Apache 2.2.3 with proxy and load balancing enabled.

  143. Cyrille Says:

    I am trying to build fro ma Windows XP workstation and I can’t install mongrel_cluster. I get the following error:

    “Failed to build gem native extension”

    (as far as I understand, mongrel_cluster doesn’t exist for Win32).

    But it looks like a don’t really need mongrel_cluster: only the recipes for Capistrano.

    So, my two questions:

    1) is it possible to build from a Windows workstation?
    2) can I fake a mongrel_cluster installation by copying the recipes somewhere?

  144. sublog : Upgrading to Debian Etch for Rails Mongrel Hosting Says:

    [...] I went through the steps outline here to get Mongrel up, running and configured. Again, another problem. I had configured everything properly (I thought), but I kept getting ‘403 Forbidden’ errors when trying to access my sites. [...]

  145. www.nickhodge.com | mungenet » Blog Archive » Frankinstall Tweaking Ruby Mongrels Says:

    [...] As I planned to deploy behind Mongrel and Apache; I had to upgrade to Apache 2.2 (to get proxy_balancer), Ruby 1.8.5 (to get the latest Mongrel 0.3.13.4 with Mongrel_cluster 0.2.1) and Capistrano for remote deployment. Apart from the source, the best resource for all this text file tweaking is at Coda Hale’s site, with some extra double-cross checking from Rimuhosting’s wiki. [...]

  146. Studentbair Says:

    Cyrille - Good luck i am 99% sure that Capistrano will not work with windows I have successful set up Apache 2.2 running a Mongrel Pack (mongrel Cluster) but I could not find any nice or easy setups. You will have to do it all manually. But it I am actually running it on Windows 2003 R2 *(on a virtual server) and it runs GREAT!!! I am still having a few issues with ProxyPass and images but i am will figure it out.

  147. Studentbair Says:

    Cyrille-
    sorry i did not read your questions yes you can mimic a cluster *(i am a newbie ) so forgive me if i do not use the correct ruby terms but i believe you use Apache load balancer and then what the way i am faking a mongrel pack is with a little app called firedeamon it allows you to run an exe as a service **( i know it can be done with rails or a number of other ways but i found them to be flaky) with this app i set up 8 single instances but it works well and sort of mimics the whole pack my config for the firedeamon app is
    Short name = Railsapp1
    Display Name = Railsapp1
    Description = Mongrel Pack #1
    Executalbe: = c:\ruby\bin\ruby.exe
    Working Directory = c:\web\App1
    Parameters: = c:\ruby\bin\mongrel_rails start -d -e development -p 6000

    I have ironed out most of the kinks and it seems to be a solid set up.

  148. Intarweb while drunk: Rails, Mongrel, Apache, Capistrano and You :: Fat Penguin Says:

    [...] I’m currently putting together a Rails, Mongrel, Apache configuration (maybe capistrano….). I was glad to find this article while looking how to use apache, with mod_proxy_balancer, and Mongrel instances. [...]

  149. Tony Rose Says:

    Hi -

    Just got this all working with a perforce repository, and FC6. Tookl about 4 hours, but have my first scaffolded table running… weee :) …

    There were a few hiccups, this article and everyones feedback helped out a great deal. On FC6 out of the box I had to modify the setenforce for SELinnux (Security Enhanced Linux) in order to allow apache to talk to mongrels. I found the easy way to do this is and preserve on reboot was to modify /etc/selinix/config to SELINUX=permissive. There are probably more secure ways to do it, but this box is behind all types of firewalls so not too worried.

    Thanks for the great article!

    Tony

  150. Debian On Rails : Apache 2.2 + MySQL + Ruby + Rails + PHP + Mongrel + Mongrel_cluster + Subversion + Trac + Capistrano Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  151. Richard Crowley Says:

    Great article, Coda. I probably owe you a pint once I move to the Bay Area. I documented my setup process for this type of Apache / Mongrel cluster on Ubuntu following most of your steps. Where I lost you is in what exactly Capistrano does. Does it just do the heavy lifting of pushing what’s in your Subversion out to some production server? If so, nifty, if not, confusing. Thanks again,
    Richard

  152. Stoneageblog.com » Blog Archive » Debian On Rails : Apache 2.2 + MySQL + Ruby + Rails + PHP + Mongrel + Mongrel_cluster + Subversion + Trac + Capistrano Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  153. Giuseppe Says:

    Great article, Coda.

    however, um, I am sort of stuck here:

    > Finally, link your mongrel_cluster.yml from your
    > app’s config directory to /etc/mongrel_cluster:

    how can I create a link to a file that does not exist yet? Isn’t the whole app tree going to be put by capistrano inside a directory named like YYYYMMDDHHMMSS upon deployment (which is the next step in the process)?

    So, what should I replace /your/rails/app with in the following:

    sudo ln -s /your/rails/app/config/mongrel_cluster.yml /etc/mongrel_cluster/yourapp.yml

    I must be missing something obvious… sorry in advance.
    Giuseppe

  154. Richard Says:

    This is a great article and has helped me setup my site, but has anyone else noticed a 15 second proxy timeout when the Mongrel servers are busy or slow? I am using this same setup except I’m using Apache 2.0 and a hardware load balancer instead of mod_proxy_balancer. I’ve tried setting ProxyTimeout and that never works either. I’m just wondering any of you guys have seen this also.

  155. Mike Says:

    you can pass you svn project’s password into cap (and thereby avoid having to do a gratuitous svn co on each server) by adding it to the “checkout” variable.

    Heres an example (I use export instead of co) in the deploy.rb file under the OPTIONAL VARIABLES section:

    set :checkout, "export --password 'passwordgoeshere'"

  156. Tony Rose Says:

    I was inspired to actually create a blog for myself so I could post the instructions for how to host multiple rails apps under a single domain with Apache2.2 and Mongrel. I looked and looked and did not find anyone had written up how to do it so here you go! … It took a while to figure out, but was pretty simple once I understood all the moving parts. That seems to be a common theme in RoR!

    http://tonyrose023.blogspot.com/2007/01/multiple-rails-apps-with-mongrel.html

  157. Robert Synnott » Blog Archive » Setting up Ruby on Rails app on a creaky old Debian Stable box - quick guide Says:

    [...] with Apache 2.0.x. Now, at some point, I realise, I should upgrade to Apache 2.2.x and do the whole Mongrel/mod_proxy_balance thing, or else use lighttpd. But for the moment, I have a slightly exotic Apache config that I [...]

  158. An Adventure into Industry Says:

    Goodbye (notso)fastcgi, Hello Mongrel…

    I’ve just started using Mongrel instead of fastcgi for my Rails apps. Its only been a few days but I’m already loving the difference. Its so much faster than before. It wasn’t hard setting up either. Now Apache just proxies requests t…

  159. The Bark Blog » Nginx at 10,000 Feet Says:

    [...] “Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You” by Coda Hale [...]

  160. koolb Says:

    Ok got things running with a mix of railsmachine and capistrano and some research.

    I saw a previous post where 403 Forbidden errors were popping up. It took me a while of digging and finally found the solution:
    for those on Apache2.2 go to the mods-available/ directory under apache2 config. The file is proxy.conf and you will want to change the ‘Deny from all’ line to ‘Allow from all’. Be sure ProxyRequests are off or else I think you become an open proxy for anyone on the internet — which is bad.

    I also added the following line to the “check for static” section of the Rewrite rules:

    RewriteRule ^/(stylesheets|images|javascripts|favicon.ico) /$1 [QSA]

    Not an apache2 guru but this may save someone the hair-pulling I went thru.

    One final note: I have configured apache2 so that I can use appname.mydomain.dyndns.org and the railsmachine gem will add an application to my dyndns domain which is very nice (all I need to do is select a different start port, eg 8010, 8020 for each app).

    Railsmachine will even configure an /etc/mongrel_cluster/myapp.conf for each set of clusters and a unique id, eg, ‘balancer://myapp1_cluster’, keyword in the apache2 configurarion). I am not too fond of the mydomain/app1 mydomain/app2 paradigm.

    No need to purchase a monthly contract with anyone for your own apps - you will need to provide your own fault-tolerance tho.

    Thanks for the great info. Been a while (1.3) since I have configured apache and it was a challenge since I knew very little about proxys and load balancing. Also a rails noob but liking it a lot, comming from C++, Perl, Python and living thru PHP programming hell.

  161. David Says:

    A problem I ran into: I have a couple of environment variables that were not getting set when the mongrel_cluster was starting thus my pages were not being served correctly.

    Solution: I added the environment variables to the /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/resources/mongrel_cluster
    file.

    export MYLIB=somelib
    They are now being set when the mongrel_cluster service starts.

  162. Marg Says:

    To you on a site my calls of son often.I looked satisfied also to me.To me, satisfied, this which he was in you on a site.
    disability insurance claims declination letters

  163. Casey Helbling Says:

    Richard (154) — I have been noticing timeouts and things too recently on my latest rails project nearbie.com — actually I have been receiving

    “Proxy Error The proxy server received an invalid response from an upstream server. Reason: Error reading from remote server”

    but it very much feels like a TimeOut issue since the server delays as it is processing an image (resizing a bunch of thumbnails). I tried what this guy was saying but it didnt seem to help either.

    http://blog.pomozov.info/posts/apache-mongrel-and-proxy-error.html

    Any other thoughts would be greatly appreciated!

    Thanks,
    Casey

  164. Blaness.com » Blog Archive » Restart Mongrel Cluster on Apple OS X with Launchd Says:

    [...] that I have developing. I decided on a production environment based on Coda Hale’s “Time For A Grown-Up Server” setup. Fortunately MacPorts (formerly Darwinports) makes it extremely easy to setup Apache 2.2 and [...]

  165. Fun with hosts, virtual and otherwise Says:

    [...] former is considerably easier to set up. But I followed these instructions to the letter, and many others, and I found that no matter what I did, all of the URLs worked fine within Mongrel and were [...]

  166. Amir Says:

    I’m deploying from a Windows system, and the deployment doesn’t run as root (but as a normal Linux user). However, the chkconfig statements sets the mongrel_cluster to start as root.

    So, after server boot, if I use capistrano to update, it cannot touch the mongrel_cluster.

    Should I deploy as root? (I don’t like this idea of sending the root password on every deploy).
    Otherwise, how do I change the chkconfig of mongrel_cluster to run as my normal user instead of root?

    Thanks,
    Amir

  167. nonsens » Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda Hale Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  168. Wishlisting Blog » Blog Archive » Deploying Ruby on Rails, Mongrel, and Pen on a MediaTemple (dv) 3.0 Server Says:

    [...] I wanted to use Mongrel instead of FastCGI. [...]

  169. Giuseppe Says:

    Hi Coda, thanks once again for the effort.
    I got soooo close, but now I seem to be stuck on 403s.

    * my apache2.2 (on Ubuntu) also serves non-rails pages, so I set up a separate virtual host for my rails app
    * 2 mongrels are properly running on ports 8300 and 8301 (the application runs fine if invoked from the LAN on either port with “address: 127.0.0.1″ commented out in mongrel_cluster.yml)
    * I have fixed proxy.conf as koolb suggested on Feb 12
    * I have tried the following both in a separate file in conf.d, and inside the relevant vhost, as suggested in RimuHosting Bliki

    BalancerMember http://127.0.0.1:8300
    BalancerMember http://127.0.0.1:8301

    Still, if I try http://myapp.com I get “403 Forbidden” errors, and myapp_errors_log reports the following:


    client denied by server configuration: proxy:balancer://mongrel_cluster/

    Any clues of what I might be doing wrong? I could provide all relevant config files, but I do not want to clutter this space or abuse your patience… :-)

    Cheers,
    Giuseppe

  170. Giuseppe Says:

    er, my attempt at marking up my previous post resulted in a bit of code being eaten up. I meant:

    BalancerMember http://127.0.0.1:8300
    BalancerMember http://127.0.0.1:8301

    Thanks again,
    Giuseppe

  171. Tom Says:

    Hey Casey (#163). I was seeing the same thing with my install and then found, inexplicably, that it went away when pen was run in the foreground (-f flag).

    I added it to my troubleshooting section here:
    http://blog.wishlisting.com/?p=20

    Hope it helps… and I’m even more hopeful that someone can figure out WHY it helps.

  172. tjc Says:

    If you get 403 errors with corresponding apache log entries of “client denied by server configuration: proxy:balancer://…”, your mod_proxy config is blocking your local balancer config.

    On Debian etch (and Ubuntu) look at /etc/apache2/mods-available/proxy.conf:


    AddDefaultCharset off
    Order deny,allow
    Deny from all
    #Allow from .example.com

    Rather than override that, add this to your Mongrel cluster proxy definition (along with the 127.0.0.1 lines:


    Order allow,deny
    Allow from all

    Problem solved

  173. Some EC2, Fedora, Rails, Mongrel, Memcached Links - Laughing Meme Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You - never had much luck with Pen and co — Apache2’s proxying modules rawk! [...]

  174. Olive Says:

    Thank your for this nice article, Coda. I think it help really a lot of user who have to start with Cap’

    Could I ask you something happend on my server ?

    What’s difference between task :deploy and task :cold_deploy about “restarting” Mongrel ? Because, on my server I have no problem with the restart from task :cold_deploy, but on error occurs with the restart from task :deploy…

    As you could see here:
    executing task restart

    executing “cd /var/www/rails… && mongrel_rails cluster::stop”

    Stopping 3 Mongrel servers…
    …/mongrel_rails:162:in `kill’
    Operation not permitted

    Any idea ?

  175. Cog Blog » Blog Archive » Holy Grail of Rails Servers Says:

    [...] found Coda Hale’s post on rails mongrel apache and capistrano very [...]

  176. m Says:

    Hi,

    Thanks for the great write-up.

    How can I change my rewrite-rules to allow http access to svn on the same server?

  177. Marcel de Graaf Says:

    Hey Coda, thanks a lot for your detailed and useful article, it really helped my setting up our new dedicated server for our Rails app.
    Thanks!

  178. koolb Says:

    TJC! Thanks for the tip! Much better editing the proxy config there.

    I didnt see mention of the use of the railsmachine gem but just about all this apache2 config is set by the railsmachine gem rule:

    cap -a setup
    cap -a setup_servers
    cap -a cold_deploy

    BTW, I have a script that takes a default Knoppix 5.1 disc and brings it to a state ready for deployment of your application.

  179. Jan Wikholm Says:

    You fokken rule!

    This saved my night.

  180. Losing My Job Apache 2.2 + Mongrel Cluster « Says:

    [...] some more searching and found that Coda Hale has the most elegant solution to the problem. I simplified his solution to the steps below. But before trying anything, you [...]

  181. Justin Turner Says:

    Thanks Coda,
    Excellent write up on a solid configuration.

  182. koolb Says:

    Re: Setting up SVN on same server.

    I use SVN on the same server as my rails demo box (the place where my apps live until payment is received. hehe).

    Be sure to create an apache2 config for each host name. sites-available/default should be there already, eg (sites-available/svn,app1,app2) for each host name (all resolving to the same external ip addy).

    Put ONE and ONLY ONE NameVirtualHost 192.168.0.10 in ONLY your default host site config file (took me a while to “get” this).

    In each other host site config (either a COPY of default or created from the railsmachine: cap -a setup_servers cmd): eg:
    sites-available/svn:

    ServerName svn.mydomain.com

    a2ensite svn

  183. Navneet Aron Says:

    Thanks for an awesome post. It was very helpful. After successful deployment, I’m running into something unexpected.
    I’ve mongrel cluster with Apache2 proxy balancer. It seems Apache has cached some content and even if mongrel cluster is shut down, Apache serves up that content. Even when Mongrel cluster is running, still the same STALE content is served.
    Any ideas on how this can be resolved?

    Thanks
    Navneet

  184. links for 2007-05-30 « J.Uma Shankar Ladha Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … talling sendfile, but it doesn’t help–Apache serves the static content, so the 20%-or-so boost on static files is never seen–and it can even cause some pretty severe stability issues. So. No sendfile, and if you’ve got it installed, uninstall it, (tags: rails apache rubyonrails capistrano howto performance) [...]

  185. Jeremy Walker Says:

    Just to say thank you for this post, its invaluable.

  186. Martello » Apache + Mongrel on Solaris Says:

    [...] owe a great deal of thanks to this article posted by codehale on the same topic. The article you are reading here is a summation of [...]

  187. Valery Khamenya Says:

    I ve got all this cool tutorial through. the only trouble: only a http://myapp.com/ is proxied OK. Any other path supplied after “/” is not proxied. I guess smthing goes wrong with rewrite rules, but no idea what….

  188. Paul Dowman » Blog Archive » I’ll set up your Ruby on Rails server for you. For free. Says:

    [...] are you need almost the same configuration as me. As of this writing 1845 people have bookmarked Coda Hale’s excellent guide to setting up Mongrel + Apache on del.icio.us. The article has 187 comments. Why should so many people each have to do the same [...]

  189. Daniel Says:

    Getting an error when I try to do the cold deploy - anyone have any ideas what I did wrong?

    sudo mongrel_rails cluster::start -C /var/www/spit_your_best_verse/current/config/mongrel_cluster.yml
    /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/lib/mongrel_cluster/init.rb:23:in `merge!’: can’t convert String into Hash (TypeError)
    from /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/lib/mongrel_cluster/init.rb:23:in `read_options’
    from /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/lib/mongrel_cluster/init.rb:27:in `start’
    from /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-0.2.1/lib/mongrel_cluster/init.rb:95:in `run’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/mongrel/command.rb:211:in `run’
    from /usr/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails:243
    from /usr/bin/mongrel_rails:16

  190. fact4s.me.uk weblog » Blog Archive » links for 2007-06-29 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … mongrel_rails cluster::configure -e production -p 8000 -a 127.0.0.1 -N 3 -c /path/to/your/capistrano/setup’s/current (tags: mongrel rubyonrails apache2) [...]

  191. Julian On Software » Where are the locations of Ruby on Rails logs? (aka how do I find out what the error was in Rails) Says:

    [...] Hale write a great piece on best practices for Mongrel / Apache integration and talks about Capistrano (the deployment framework).           0 [...]

  192. Rails Deployment « Code Prostitute Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  193. Alex Says:

    Thanks for an excellent tutorial, Coda. A year later it’s still very useful.

    I wrote up some instructions for adding Capistrano 2.0 to an existing Apache/Mongrel/Rails mix, if anyone is interested.

  194. Paul Dowman Says:

    This has been really useful for me, thanks Coda! For Amazon EC2 users: I have created a public server image that is set up based on this article, for more info see:
    http://pauldowman.com/projects/ruby-on-rails-ec2/

  195. busha.net » Blog Archive » Mongrel Says:

    [...] very thoroughly. Check out Mongrel’s site for more information. I would also recommend this guy’s site, but you’re smart enough to use google, I’m sure you can find your own [...]

  196. Rails: Apache 2.2 vs nginx 0.5.30 » stinger’s thoughts Says:

    [...] конфигуриране на Mongrel cluster, вижте страхотната статия на Coda Hale. За коректна Debian-базирана инсталация на Rails - вижте [...]

  197. 網路創業、web2.0技術、快樂生活 » Blog Archive » Ruby on Rails + Mongrel_cluster…續 Says:

    [...] 1. http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-y... [...]

  198. A Noted Path » I need mod_proxy_balancer? Says:

    [...] Time For a Grown-Up Server [...]

  199. Laurie Young Says:

    Thanks for the article, I had some strange problems with apache which I finally solved (with the help of a friend) so I thought I would put the fix here in case anyone else has the same problem.

    Upon trying to start Apache I got the error “BalancerMember Can’t find ‘byrequests’ lb method”. It turns out that you have to make sure you load mod_proxy, and mod_proxy_balancer. I only had mod_proxy loaded, which defines the “BalancerMemeber” directive (so I didn’t get Directive Not Found errors”, but doesn’t allow you to use it.

  200. peter Says:

    It all ran well until cap cold_deploy

    cap cold_deploy
    the task `cold_deploy’ does not exist

    And there isn’t even a cold_deploy.rb in my filesystem.

    Same with
    cap deploy
    the task `deploy’ does not exist
    Although I edited the
    /var/lib/gems/1.8/gems/capistrano-2.0.0/lib/capistrano/recipes/deploy.rb

    cap -T
    cap invoke # Invoke a single command on the remote servers.
    cap shell # Begin an interactive Capistrano session.

    Any Idea?

  201. Mongrel Cluster and Apache Need Memory Says:

    [...] mongrel instances are proxied behind Apache using mod_proxy_balance as described here. This setup works very well and is more and more becoming the defacto standard for deploying Rails [...]

  202. peter Says:

    I found out I used capistrano-2.0.0.

    I downloaded capistrano-1.4.1.gem from the sourceforge website and installed it after unbinstalling capistrano-2.0.0.

    Now cap cold_deploy and cap deploy works.

  203. Daniel Says:

    Thanks for your great tutorial. I managed to get everything up and running. I had to do some things manually, because I couldn’t get Capistrano 2 work smoothly together with mongrel cluster and I have another problem. I missed something while configuring Apache, because when I browse through my application it won’t show any pictures in the images folder and it won’t link correctly to the stylesheets folder. Do you have any suggestions? Thanks for any help! Greets, Daniel

  204. Dugu Says:

    Thanks for the tips. It was really easy to work things out. Cheers

  205. JanM Says:

    About the apache.conf:
    I think this line has a superfluos ‘/’ in the middle (but works apparently):
    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f

    also, you don’t need the ( and ) on this line, since you’re not referencing the match:
    RewriteRule ^/(.*)$ balancer://domain.com_cluster%{REQUEST_URI} [P,QSA,L]

  206. Apache and Mongrel at Haru’s Diary Says:

    [...] to use Apache2 as a kind of Proxy for Mongrel. It turns out that there’s a great one over at CodaHale. So if you’re looking for something like I did, I would really recommend this [...]

  207. jereme Says:

    I’m running into a problem with the Apache2 setup. Every time I try and access the site I receive a “404 Not Found” page. I’m guessing the rewrite rules are not in effect, but have no clue how to make them work properly.

    I’m trying to set up redMine in Ubuntu.

    Any help is much appreciated!

  208. Scott Says:

    Casey and Richard:
    I was having similar issues. Finally figured out that I had to add
    Timeout AND ProxyTimeout to the Virtual Host. So:

    Timeout xx (seconds)
    ProxyTimeout xx (same number of seconds)

  209. phil Says:

    Thanks for this excellent walkthru.

    I used it to setup Apache 2.2, Mongrel 1.0.1, Mongrel Cluster 1.0.2,
    Rails 1.2.3 on Debian Etch.

    I used the following commands to enable all required modules for
    apache.


    a2enmod rewrite
    a2enmod deflate
    a2enmod proxy
    a2enmod proxy_balancer
    a2enmod proxy_http

    It took me a while to figure the last one out, although I’ve to admit
    that the error message was quite precise:


    No protocol handler was valid for the URL /. If you are using a
    DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

    In addition to the steps mentioned here I had to create two symlinks
    to make my system find mongrel’s executables


    ln -s /var/lib/gems/1.8/bin/mongrel_cluster_ctl /usr/bin/mongrel_cluster
    ln -s /var/lib/gems/1.8/bin/mongrel_rails /usr/bin/

    I’m not sure this is the way it’s meant to be, but it worked for me.

    I put my app’s config for apache in one file
    /etc/apache2/sites-available/myapp and enabled it issuing


    a2ensite myapp

    Debian users might want to change the location of the logfiles, as
    well as the previous mentioned proxy section, adding


    Allow from all

    to avoid 403 Errors.

    On my freshly setup etch I also had to edit
    /etc/apache2/sites-available/default changing the asterisks of the
    first and second line to the machine's ipaddress, appending the ports
    (one NameVirtualHost for each port) due to the following error (I also
    did this for myapp):


    mixing * ports and non-* ports with a NameVirtualHost address is not
    supported, proceeding with undefined results

    It now reads like this:


    NameVirtualHost xxx.xxx.xxx.xxx:80
    NameVirtualHost xxx.xxx.xxx.xxx:8080
    <VirtualHost xxx.xxx.xxx.xxx:80>
    ...

    I’m sure I forgot to mention something, sorry for that.

    Oh, I changed the setup of the Mongrel Cluster from three to four
    workers, because for a dual core machine it just felt right to have a
    multiple of two, but I am now pro on that topic. ;)

  210. Chetan Patil Says:

    Looks like my earlier comment didn’t get through…
    ————-
    Thanks for the writeup Coda. Very helpful.

    To make the above setup more secure to deny .svn/* requests, add the following rewrite rule to myapp.common

    # Uncomment for rewrite debugging
    #RewriteLog logs/myapp_rewrite_log
    #RewriteLogLevel 9

    # Don’t allow any .svn accesses
    RewriteRule ^(.*/)?\.svn/? - [F,L]
    ErrorDocument 403 “Access Forbidden.”

    # Check for maintenance file and redirect all requests
    RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f

    Of course, you can avoid having .svn directories in the released code by configuring Capistrano to use svn export instead of svn checkout. But I had an older setup that I don’t want to update to the new Capistrano version yet.

    Adding

    Order allow,deny
    Deny from all

    didnt’ help since the RewriteEngine was still matching the request and passing it on to the proxy. It took me some time to figure that out, so wanted to throw it out for others.

  211. Chetan Patil Says:

    Messed up the formatting:

    The DirectoryMatch code that didn’t work is:

    <DirectoryMatch “^.*/\.svn/”>
    Order allow,deny
    Deny from all
    </DirectoryMatch>

  212. Rails server configuration « Technology Forward Says:

    [...] http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-y... [...]

  213. Christian Frugard Says:

    I am using a Mongrel + Apache 2.2 configuration. It works great, and I am able to rewrite the remote_user header so we dont have a login page (on intranet). Problem is, when using Ajax calls, it any request parameters are lost on repeated, quick requests. If the user waits more than about 5 seconds between requests, the request is fine; less than that, the paramters are lost. This only happens when proxying through Apache. Has anyone else seen this behavior?

  214. David Badawi Says:

    Incredibly useful tutorial. Thanks for taking the time to share and teach.

  215. BruceH Says:

    On the security issue, what if I only want to secure the Rails app? Would the config for SSL change? And what if I wanted to leave a couple of Rails requests (let’s say all that reference a particular controller) open to the world (i.e. search and view), but the rest of the app (DB maintenance) pieces will be secured. How would that change the config?

  216. BruceH Says:

    I meant to add that the static content would NOT be secured.

  217. links for 2007-10-12 « Caiwangqin’s delicious bog Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … (tags: deploy rails mongrel capistrano) [...]

  218. viktor tron Says:

    update on comments 194
    check this out for a rails virtual appliance
    http://ec2onrails.rubyforge.org/

  219. Simplistic Complexity » Clustered Mongrel In A Shared Environment Says:

    [...] you’ve read Coda’s motivating post on getting this stack up and running, then some of this will be familiar to you. I’d suggest [...]

  220. Simplistic Complexity » Apache 2.2, mod_proxy_balancer, & Mongrel on Ubuntu 6.06 Says:

    [...] comes strait from Coda, which came strait from Zed. And you listen to [...]

  221. Jónas Tryggvi Says:

    Hi and thanks for a great article. I used it as a reference while setting up my system, and everything works great!

    BUT; when using Safari 3 on Windows on HTTPS parts of the web which is served by Apache 2.2, images start to randomly disappear. Any ideas on what is happening? This is probably a SSL/Apache issue, but I couldn’t find anything on it anywhere.

  222. guitargeorge Says:

    I’ve never heard about Capistrano before, but now i don’t wanna miss Capistrano.

  223. Ruby on Rails applications with Mongrel cluster and Apache url rewriting on Ubuntu : Thinking in GIS Says:

    [...] blog.codahale.com kpumuk.info Bookmark [...]

  224.   Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | codablog | Coda Hale by CRACKMAC.COM Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | codablog | Coda Hale More and more Rails developers are finding out that deploying a Rails application isn’t as simple as upload and rename; Rails apps work best when running all the time, and many Rails programmers are moving from traditional, shared hosts, like Dreamhost, to virtual private servers, like Rimuhosting, which allow them full control and responsibility of production servers. [...]

  225. taylordavis.com » Blog Archive » links for 2007-11-28 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … (tags: rubyonrails reference) [...]

  226. Unixmonkey.net » Blog Archive » BigNerdRanch Ruby on Rails Retreat Says:

    [...] Lastly, we talked about deployment, and how Charles’ preferred method for deployment is Apache+mongrel. We talked about Capistrano and the way it maintains symlinks to the current svn pulldown for versioning and easy rollback. An excellent article on deploying with apache and mongrel is Coda Hale’s Time for a Grown Up Server. [...]

  227. » links for 2007-11-26 | Paul Cowles Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … talk of setting up mongrel clusters (tags: rails hosting) [...]

  228. Stonie’s Linux Sachen » Blog Archive » Ein stiller Wechsel Says:

    [...] hat sich das Ruby-basierte Typo als nicht sehr performant erwiesen. Dies obwohl ich ein Mongrel-Cluster-Setup ausprobiert hatte, dauerte das Rendering der Index-Seite teilweise über 40 Sekunden, wenn das [...]

  229. 2dc Says:

    Hi,

    Thanks for this howto.

    I just have a problem with static files (images, css, …), they are rendered very slowly. I have messages like this for every static file in my log :

    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^/$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^([^.]+)$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^/(.*)$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (4) RewriteCond: input=’/var/www/rails/myapp/public/images/logo.png’ pattern=’!-f’ => not-matched
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (1) pass through /images/logo.png

    Do you have any idea? :(

    Thanks in advance!

  230. 2dc Says:

    Hi,

    Thanks for this howto.

    I just have a problem with static files (images, css, …), they are rendered very slowly. I have messages like this for every static file in my log :

    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^/$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^([^.]+)$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (3) applying pattern ‘^/(.*)$’ to uri ‘/images/logo.png’
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (4) RewriteCond: input=’/var/www/rails/myapp/public/images/logo.png’ pattern=’!-f’ => not-matched
    [21/Dec/2007:10:58:26 +0100] [myapp.com/sid#800f64c0][rid#80242a80/initial] (1) pass through /images/logo.png

    Do you have any idea? :(

    Thanks in advance!

  231. Unixmonkey.net » Blog Archive » Setting up a production rails server step-by-step Says:

    [...] For Rails, there are lots of deployment strategies, some are tuned for compatibility with shared hosting (fastcgi), and some are built for speed and minimum configuration (Litespeed Nginx and Lighttpd), and some are built to leverage the strength and flexibility of stable and established server software (Apache+Mongrel). [...]

  232. links for 2008-01-05 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda … (tags: capistrano deployment mongrel rails) [...]

  233. schroedi Says:

    The best Tutorial I ever read.

    Great Stuff

  234. Zed Shaw—Holy Crap | Hot Media Mess Says:

    [...] Thankfully, the sites I’ve deployed with RoR have caching in place, and essentially amount to a simple static HTML site for Apache to spew out (courtesy of this post). [...]

  235. maha Says:

    am a newbie to ubuntu. iam totally lame about the concept. so will you kindly tell HOW To starting from apache2.2 and mainly the location of the folders containing the file. my task is to deploy a web server with apache2 with fastcgi & ruby on rails & mongrel & mod_proxy_balancer.
    can you pls help me…

  236. Carlos Says:

    works perfect!! thank you very much!!

  237. Maxime Says:

    Very useful post. It helped me a lot.

    Thanks!

    Maxime

  238. rufio Says:

    Hi, can I set up for more applications (domains). If Yes, do U know how? Many thanks!!!

  239. G Says:

    Thanks for the article. It was helpful, especially the SSL section.

  240. Sam Saffron Says:

    I second Ray on the x-javascript issue, My apache debian server has the same issue, it serves out javascript as x-javascript

    Also, YSlow recommends adding expire tags which I did in the following way …

    ExpiresActive On
    ExpiresByType text/css “access plus 1 month”
    ExpiresByType text/javascript “access plus 1 month”
    ExpiresByType application/x-javascript “access plus 1 month”
    ExpiresByType image/png “access plus 1 week”

    On another note I noticed this gravatar support is a performance hog, it may make sense to pre-cache images on the server …

  241. Brian Moschel Says:

    This tutorial got me most of the way through initial deployment. Thanks for your hard work. Another series of Deployment 101 articles that might be helpful is posted here:

    http://jupiterit.com/wordpress/?p=190

    I documented all the problems I had with deployment and created a step by step guide for each stage. Hope its helpful.

  242. Tech Messages | 2008-02-04 | Slaptijack Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda …Walk-through to help you get your Ruby on Rails application up and running as soon as possible. [...]

  243. nosyjoe Says:

    to all who get the rrror message

    !! Path to log file not valid: log/mongrel.log

    In my case it helped when I added the following line to my mongrel_cluster.yml config file:

    cwd: /home//current/

    hope that helps!

  244. Scott’s Feed Reader » Blog Archive » Tech Messages | 2008-02-04 Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You | Archives | codablog | Coda …Walk-through to help you get your Ruby on Rails application up and running as soon as possible. [...]

  245. Vuelos Says:

    works perfect!! thank you very much!!

  246. Fiid’s Blog » Blog Archive » Rails: The Other Foot. Says:

    [...] reveal yet more information, including the “pack-of-mongrels” approach which is detailed on Coda Hale’s blog. Thanks to both of these guys for very succinctly laying out solutions and issues on rails [...]

  247. Deploying Ruby on Rails with Capistrano on DreamHost — Glenn Fu Says:

    [...] you don’t like the trouble caused by dealing with Ruby on Rails on DreamHost, check out this article for some ideas of good [...]

  248. some probably useful links to get into Ruby on Rails « Arnold Funken on social site building Says:

    [...] rails x apache [...]

  249. Kris’ Blog » Blog Archive » Rails deployment Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  250. Common Media, Inc. » Blog Archive » Y Be Slow? Says:

    [...] are already compressed, so re-compression won’t help and might hurt.) If you’re using Coda Hale’s configuration for Apache and Mongrel (and many of us are) the code for compressing text components before download is already in your [...]

  251. betweenGo » Configuring Capistrano and Mongrel Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  252. betweenGo » Configuring Apache to work with a Mongrel Cluster Says:

    [...] Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You [...]

  253. Zone of Mr. Frosti » Blog Archive » How to setup a Hoard of Mongrels Says:

    [...] there isn’t much on the subject floating around out there. Problem #2 is what I did find was geared towards Capistrano (another layer of complexity I was hoping to avoid). Problem #3 is this seems to be even [...]

  254. control time from server Says:

    [...] [...]

  255. Andrew Pennebaker Says:

    Can you help me with a Ruby question? I’m not sure if it’s Ruby’s fault or Ubuntu’s fault, but I’m getting an error following your directions.

    sudo gem install daemons gem_plugin mongrel mongrel_cluster –include-dependencies
    Need to update 1 gems from http://gems.rubyforge.org
    .
    complete
    ERROR: While executing gem … (Errno::EROFS)
    Read-only file system - /var/lib/gems/1.8/source_cache

    Upon subsequent attempts to install daemons or mongrel_cluster, I get the error:

    sudo gem install mongrel_cluster –include-dependencies
    ERROR: While executing gem … (Errno::EROFS)
    Read-only file system - /root/.gem

  256. Peter Williams - mod_proxy_balancer Is A Two Timing Hussy Says:

    [...] see what I mean lets start with what Google suggests. The reverse proxying gets setup something like [...]

  257. harbans Says:

    hello friends, iam looking for an answer of my question regarding deploying of ror app on different servers. Question is that : can we deploy our app on different servers without using capistrano? How much work and what type of work have to be done to deploy such app?
    i will be thankful to you.

  258. harbans Says:

    Hello ,

    My previous seminar went well. Now I have an another query, if you help me in this also.
    As there is a concept of remoting in .net,
    is this possible to deploy the components in ROR and to make these components communicate with each other as done in remoting concept?
    Is this possible in ROR?
    Please guide me.

    Thanks
    Harbans

  259. Babble On » Blog Archive » Passenger (mod_rails) vs Apache/Mongrel Says:

    [...] been a long time advocate of the Apache/Mongrel Rails ever since Coda Hale blessed us with it some time ago, I’ve not since paid a huge amount of attention to the alternative Rails [...]

  260. Aikidev.com » Amazon EC2 - Configuring web server Says:

    [...] this blog post for information on configuring [...]

  261. thebalance » Blog Archive » The local_request That Isn’t Says:

    [...] on the same server as your mongrel_cluster using a configuration similar to the one outlined here, then request.remote_addr will always be 127.0.0.1, because the request is really coming from your [...]