Tuesday, March 16, 2010

Running Rails on IIS 7 using FastCGI

Recently I took a journey into IronRuby.Rack and found that it's not quite ready for prime time yet. However, what does work is URL rewriting and FastCGI on IIS7. For the record, if you can avoid doing this, please do!

Props to these references for getting me started.


Here is what -I- did

Enable FastCGI support in IIS7

http://learn.iis.net/page.aspx/246/using-fastcgi-to-host-php-applications-on-iis-70/#EnableFastCGI

Install URL Rewrite module

Using the Web Platform Installer I installed the URLRewrite module.

Install Ruby

Obtain the Ruby MSI Installer for windows and run it keeping all the defaults (ex. Install location => C:\Ruby)

Update Rubygems

Open a terminal window and run the following:
gem update --system

Install Rails

gem install rails --include-dependencies

Install Sqlite3

NOTE: This approach seems to work fine for 32 bit Windows installs, not for 64 bit.
To get started grab sqlitedll-3_6_23.zip from the sqllite website.
Expand the zip and copy both files (sqlite3.def, sqlite3.dll) to C:\Ruby\bin
Then install the sqlite gem by running:
gem install sqlite3-ruby --include-dependencies
For additional information on this step you can refer to this post.
Verify the step worked by running
gem list

Put a Rails app on your machine

At this point, we are getting close. You can either create a brand new Rails app by running
rails myapp

rake db:migrate
Or copy an existing Rails app to your machine.

Setup up web site in IIS7

Open the IIS management application.
Add a new website and point it to your Rails sites public folder.
Click on the website and you should see a "Handler Mappings" option. Click it and then select "Add Module Mapping ...".
  • Set the Name to Ruby via FastCGI


  • Set the Request Path to dispatch.fcgi


  • Set the Module to FastCGIModule


  • Set the Executable to C:\Ruby\bin\ruby.exe|C:\myapp\public\dispatch.fcgi development


  • I also added an entry in my hosts file for my Rails app.
    127.0.0.1  myapp

    Add URL Rewriting Rules

    In the same section as the "Handler Mappings", there should be a "URL Rewrite" option, open it.
    Select "Import Rules ..." and paste the following in
    # Redirect all requests not available on the filesystem to Rails
    RewriteEngine On
    RewriteRule ^$ index.html [QSA]
    RewriteRule ^([^.]+)$ $1.html [QSA]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
    
    It should show you the rules in the TreeView with green checkmarks. If so, then save and apply those rules.

    Create your dispatch.fcgi

    I used this simple dispatcher for my Rails app, use it to get you started.
    require File.dirname(__FILE__) + "/../config/environment"
    require 'fcgi_handler'
    
    RailsFCGIHandler.process! nil, 10
    
    Save it as dispatch.fcgi in your Rails apps public folder.

    Permissions!!

    If you were to view the site now, you would probably be met with a 500 error. To resolve this, add NETWORK SERVICE to your Rails app folder and give them Full Control.
    This part of the process is a pain and I'm sure it's slightly different for everyone depending on their server config and version of Windows.If NETWORK SERVICE does not solve it, verify that
    it is a permissions problem by allowing Everyone access to the Rails app. If that allows you to load the site, then REMOVE Everyone and try to narrow it down to the required account.

    Reset IIS

    64 bit

    If you are running on 64 bit, you can enable 32-bit applications in the application pool for your site under Advanced Settings.

    My problems

    SQLite3 gave me all kinds of trouble. I finally abandoned it and went right to MySQL. Here is the error I was seeing in my log:
    SQLite3 problem
    /!\ FAILSAFE /!\ Wed Mar 17 09:25:47 -0400 2010
    Status: 500 Internal Server Error
    127: The specified procedure could not be found. - Init_sqlite3 ./sqlite3.dll
    
    So I downloaded and installed MySql and selected mysql-essential-5.1.45-winx64.msi
    I then changed my database.yml to use mysql instead of sqlite3 and installed the mysql gem
    gem install mysql
    but once again, 32 bit caused a problem and I had to download another dll and copy it to C:\Ruby\bin For instructions on where to get the dll look here.

    Finished!

    So that is how I accomplished getting my Rails app running on IIS7 with Fast CGI and URL Rewrite. Good luck to you and please refer to the references I posted above to learn more about the hows and whys. Also note that those posts refer to manually editing web.config, please just use the IIS admin to edit it. For reference though, mine looked like this in the end:

    Monday, March 15, 2010

    IIS + Ruby & Rails

    I've been trying to get Rails up and and running on IIS and have had trouble finding good documentation on how to accomplish that using IronRuby.Rack. Recently Ivan Puerto Carrero posted a reply on the IronRuby mailing list describing how to get it working. I'm sharing that post here to add more visibility to the solution and will be giving it a try tonight. Hope this helps others find their way through the IIS/Ruby adventure.



    Date: Sun, 14 Mar 2010 20:38:05 +0100
    From: Ivan Porto Carrero
    To: ironruby-core@rubyforge.org
    Subject: Re: [Ironruby-core] IIS + IronRuby

    but what I did was create a new solution in visual studio
    Added references to the files from the ironruby rc3 distribution
    Add the files from Merlin\Main\Hosts\IronRuby.Rack\*.cs to the solution

    Applied this patch

    compiled as release

    Added a bin folder to my public folder and copied the resulting assemblies there.

    Added a web.config much like this one. But I changed the values of LibraryPaths and GemPath to point to my ironruby install based on C:\ironruby\

    I also changed the value of AppRoot to ..

    and my config.ru in the RAILS_ROOT contains:

    ENV['RAILS_ENV'] = 'production'
    require "config/environment"

    use Rails::Rack::LogTailer
    use Rails::Rack::Static
    run ActionController::Dispatcher.new

    That should make your application work on IIS but there is still an open problem around it not serving the images.