Home > Support > HOWTO List > Ruby on Rails Hosting Stack

Looking for the Ultimate Ruby on Rails Hosting Stack?

Rails is an incredibly popular web development framework.  It can be a bit tricky to setup.  And it requires an environment that many standard 'shared hosting' plans cannot provide.

To quote one RimuHosting VPS customer 'Rails on shared hosting sucks!'.

With a VPS setup you are more in control and you can setup a RoR hosting stack that suits your needs exactly.

All the Tools You Need. The RimuHosting Ruby on Rails Hosting Stack

Here at RimuHosting we have come up with a setup that should get you off on the right foot.  It is the RimuHosting Ruby on Rails Hosting Stack.  It includes:

By default we configured mod_rails "Passenger" with Apache.  We can also get Nginx going for you, if you need that.

If you are after this setup, just mention 'Please install the RimuHosting Ruby on Rails Hosting Stack' on the order confirmation page when/if you order a RimuHosting server (at http://rimuhosting.com/order/startorder.jsp)

For a RoR server we recommend you go with a VPS with 1024MB of memory or more (since rails can be somewhat memory hungry).

Running Rails with Apache and mod_rails (passenger)

Passenger a.k.a mod_rails is a a newish stable and fast alternative to running Rails with Apache and Mongrel. It scales well and consumes much less memory than running multiple mongrels. Plus you get the benefits of simple Apache VirtualHost configuration options and concurrency, with no proxying needed.

A simple gem install command on any of our preferred distros should do the trick:


gem install passenger
passenger-install-apache2-module
## follow the onscreen instructions ##

Then just point your Apache VirtualHost at your app's public directory and restart Apache e.g.:


<VirtualHost *:80>
  ServerName dummy-host.example.com
  # Presuming your rails app is at /var/www/rails/testapp
  DocumentRoot /var/www/rails/testapp/public
  <Directory "/var/www/rails/testapp/public">
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny  
        Allow from all
  </Directory>
</VirtualHost>

The RimuHosting Rails Stack Script

To run the RimuHosting Rails Hosting Stack script:


wget -O rails.sh "http://proj.ri.mu/rails.sh"
bash -x rails.sh

By default the script is currently installing the official Ruby 1.9.3 release with some handy Gems, a slightly newer version of ImageMagick than you will find in the latest distros and make some other tweaks to your system.  Check the available options with:


bash rails.sh -h

To install a packaged version of ImageMagick use the "-j" option.  You might want to do this, so that you can use your distro's package manager to keep up with patches.

You can view a html-ized the RimuHosting Ruby on Rails Hosting Script at: code.ri.mu.

The script is updated by us every now and then if we find it stops working for whatever reason.  If you find a problem with it or have a suggestion then pop in a support ticket and let us know and provide a 'patch' if you can.

Caveats: No warranty express or applied.  We take all care but will not be liable for any problem.  We recommend you use the script as a guide.  Do not 'just run' it.  It may format your hard drive, and electrocute your mother.  Seriously: it could potentially break your existing ruby/gem/apache/lighttpd/mongrel setup.  Look at the code carefully before running any of it on your system.

The code will 'error out' if/when it hits problems and stop at that point.  We are interested in any changes that would help us run the script on a wider variety of distros and handle a wider variety of conditions.

RVM (Ruby Version Manager)

RVM is cool! It's an actively maintained bash script for installing multiple versions of Ruby at the same time:

https://rvm.io/

The difference between our rails script and RVM is that ours is simpler and meant for production environments where you are really only intending to run one version of Ruby and keep that patched.  If you plan on setting up a more complex development environment where you will have multiple versions of Ruby/Rails/Gems, then you will want to look at using RVM to help you manage that.  If you are spinning up a VPS to run one or just a few production Rails apps, using our script is the way to go.

Somewhat obsolete information below

We have been providing Rails hosting for a long time!  Things change quickly in the RoR community.  Some notes about older types of setups below:

Using Apache as A Front End To Mongrel or Lighttpd

Try adding the following to your Apache 2.0 Virtual Host directive:


ProxyRequests Off
ProxyPass /myrailsapp http://localhost:3000/myrailsapp
ProxyPassReverse /myrailsapp http://localhost:3000/myrailsapp

__Note__: Remove any '>>' characters that the html on this page adds to that url if you copy/paste it.

(Still waiting to confirm this bit works, and it is likely different with apache 2.2).

Using Apache 2.2 with mod_proxy_balancer As a Front End to Mongrel Cluster

The Ruby on Rails dispatcher can only handle one request at a time.  It is 'synchronized' to only let one through at a time.  Why?  Since it is not designed to run multiple threads simultaneously.

For most non-slashdot-sized sites this is fine.  Since requests can execute quite quickly.

If you have a busier site though, Apache 2.2 has a new option for you.  It offers the mod_proxy_balancer module.  This lets you run multiple rails instances and then use the proxy balancer to spread your requests over multiple rails containers.

The downside is higher memory usage (so you'd need a server with more memory).

The 'balanced' rails setup would look like this:

Start your mongrels:


mongrel_rails start -d -e production -p 8000 -a 127.0.0.1 -P log/mongrel.8000.pid -c /var/www/test
mongrel_rails start -d -e production -p 8001 -a 127.0.0.1 -P log/mongrel.8001.pid -c /var/www/test

(Or modify /etc/init.d/mongrel).

Then setup an Apache 2.2 (it does not work in Apache 1.3 or 2.0) virtual host:


<VirtualHost *:80>
  ServerName dummy-host.example.com
  # Presuming your rails app is at /var/www/test
  DocumentRoot /var/www/rails/testapp/public
  <Directory "/var/www/rails/testapp/public">
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny  
        Allow from all
  </Directory>  

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

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

  # These directories should always be served up by Apache, since they contain static content.  Or just let rails do it.
  ProxyPass /images !
  ProxyPass /stylesheets !
  ProxyPass /javascripts !
  ProxyPass /favicon.ico !

  RewriteEngine On

  # Important rule to prevent exposure of subversion files if you are deploying with Capistrano !
  RewriteRule ^(.*/)?\.svn/ - [F,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]
</VirtualHost>

Running Rails With Lighttpd

There are a few options when it comes to choosing a 'front end' web server to your rails app.  Choices include Mongrel or Lighttpd.

Lighttpd is standalone web server.  It is commonly used (or at least requested) by the rails community.  You can use it to run rails apps.

After the RimuHosting rails stack is installed there will be a sample lighttpd init script in /etc/init.d/lighttpd that will stop/start a lighttpd process.

Note:
- Lighttpd would run on port 3000.  You could run it on port 80.  That would prevent you running apache on that port.  Else you'd need a different/extra IP.
- We have not setup ssl with lighttpd before.  Not sure what's involved there.

To run lighttpd with multiple domains you would setup virtual hosting.  e.g. in lighttpd.conf:


    $HTTP["host"] =~ "(www\.)?example\.com" {
      server.document-root = "/var/www/example/current/public/"
      server.error-handler-404 = "/dispatch.fcgi"
      fastcgi.server = (
        ".fcgi" => (
          "localhost" => (
            "socket" => "/var/run/www/example.com-0.socket"
          )
        )
      )
    }

    $HTTP["host"] =~ "(www\.)?example2\.com" {
      server.document-root ="/var/www/example2/current/public/"
      server.error-handler-404 = "/dispatch.fcgi"
      fastcgi.server = (
        ".fcgi" => (
          "localhost" => (
            "socket" => "/var/run/www/example2-0.socket"
          )
        )
      )
    }

More info at http://www.lighttpd.net/documentation/configuration.html

Using Apache 2.0 with a load balancing proxy As a Front End to Mongrel Cluster

Apache 2.0 does not have mod_proxy_balancer as part of the module listing. Upgrading the stock distribution's Apache installation cannot proceed though without having to recompile all applications that link to libapache (e.g. PHP, etc). However, an alternative solution to mod_proxy_balancer would be the use of a third-party application that would do the load balancing of the rails processes in a mongrel_cluster.

Popular choices that can be used as the load-balancing proxy server for mongrel_cluster include Pound (http://www.apsis.ch/pound) and Pen (http://siag.nu/pen).

Getting 'client denied by server configuration' Errors

If you're getting errors like this:


client denied by server configuration: proxy:http://127.0.0.1:8080

Check that you have something like this in your httpd.conf:


<Proxy *>
  Order allow,deny
  Allow from all
</Proxy>

In Debian and Ubuntu, this is set to __deny by default__ in /etc/apache2/mods-available/proxy.conf.

Stale PID files preventing Mongrel to start up

If you get these messages when trying to start mongrels, that's because it's not cleaning/ignoring PID files properly:


# /etc/init.d/mongrel_cluster start
Starting all mongrel_clusters...
** !!! PID file log/mongrel.8000.pid already exists.  Mongrel could be running already.  Check your log/mongrel.log for errors.
** !!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start.
** !!! PID file log/mongrel.8001.pid already exists.  Mongrel could be running already.  Check your log/mongrel.log for errors.
** !!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start.
** !!! PID file log/mongrel.8002.pid already exists.  Mongrel could be running already.  Check your log/mongrel.log for errors.
** !!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start.

Thanks to the patch provided here http://textsnippets.com/posts/show/931 you should be able to avoid that problem. Save this file as "/tmp/mongrel.patch":


--- bin/mongrel_rails-orig      2007-05-16 14:41:51.000000000 -0400
+++ bin/mongrel_rails   2007-05-16 14:42:50.000000000 -0400
@@ -83,9 +83,17 @@
       config = Mongrel::Rails::RailsConfigurator.new(settings) do
         if defaults[:daemon]
           if File.exist? defaults[:pid_file]
-            log "!!! PID file #{defaults[:pid_file]} already exists.  Mongrel could be running already.  Check your #{defaults[:log_file]} for errors."
-            log "!!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start."
-            exit 1
+            # mongrels that crash can leave stale PID files behind, and these
+            # should not stop mongrel from being restarted by monitors...
+            pid = File.new(defaults[:pid_file]).readline
+            unless `ps -ef | grep #{pid} | grep -v grep`.length > 0
+            # use "ps ax" for freebsd 
+                log "!!! PID file #{defaults[:pid_file]} exists, but is stale, and will be deleted so that this mongrel can run."
+                File.delete(defaults[:pid_file])
+            else
+                log "!!! PID file #{defaults[:pid_file]} already exists and the process id referred to in it is running.  This mongrel is probably already running.  #{defaults[:log_file]} for errors.  EXITING."
+                exit 1
+            end
           end
 
           daemonize

Then apply it by running something like this:

# patch -p0 /usr/lib/ruby/gems/1.8/gems/mongrel-1.0.1/bin/mongrel_rails < mongrel.patch

Internal Server Errors when using Internet Explorer

If you're getting Internal Server Errors from Apache when using Internet Explorer to connect to SSL pages, see if this KB article seems to match your problem: http://support.microsoft.com/default.aspx?kbid=831167

If so, the fix is to use the following in your SSL virtual host:


 SSLOptions +StdEnvVars
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0

Taken from: http://www.freeonrails.com/node/17784

Mongrel Cluster not starting up at boot

Even though you symlinked the mongrel_cluster init script to the right rc.d directory, it's not starting correctly.  In the console you might see something like this (on Centos5):


Starting mongrel_cluster:  which: no mongrel_cluster_ctl in (/sbin:/usr/sbin:/bin:/usr/bin)
[  OK  ]

Add this PATH variable to /etc/init.d/mongrel_cluster:


CONF_DIR=/etc/mongrel_cluster
PATH=/usr/local/bin:$PATH
RETVAL=0

The next time you boot, on the console you should see this:


Starting mongrel_cluster:  Starting all mongrel_clusters...
[  OK  ]

We've seen this on Centos5 and Ubuntu a few times.

rmagick is not working

most rails app uses rmagick and ImageMagick and they seem to be very version sensitive. To get rmagick working download the non-standard packages from these repositories
- RPMForge
- CentOS Plus
- EPEL

then run


yum --enablerepo=epel --enablerepo=rpmforge --enablerepo=centosplus install djvulibre-devel libwmf-devel jasper-devel libtool-ltdl-devel librsvg2-devel openexr-devel graphviz-devel gcc gcc-c++ ghostscript freetype-devel libjpeg-devel libpng-devel giflib-devel libwmf-devel libexif-devel libtiff-devel

and download again ImageMagick and recompile


wget http://downloads.rimuhosting.com/ImageMagick-6.4.3.tar.gz
tar zxvf ImageMagick-6.4.3.tar.gz
cd ImageMagick-6.4.3
./configure ; make ; make install