Skip to main content
To setup rails on IIS and enable it for multiple Applications.

START

Server 2003 Enterprise Edition SP1
IIS 6

RUBY

Install ruby 185_22_rc2.exe
You don't have to put it in c:\ruby I created the following folder c:\webdata\ruby, then ran the install.
Run install into c:\webdata and say "YES" to deleting the existing ruby directory.
During the install I ticked SciTE and Enable RubyGems
Took 10mins 1000s of files

Ruby GEMS

Install Ruby Gems 0.9.1 (don't change it from the defaults)
Extract zip file to temp directory, then double click setup.rb, does the default install (about 5mins)
Then run at the command line gem pristine --all
c:\> gem pristine --all
I tried to install Ruby Gems in a particular directory, but couldn't get it working because if you use the command line SET command to put a value into GEM_HOME when the ruby gems installer setup.rb reads the registry it doesn't account for the fact that values in the registry contain double back slashes e.g. set GEM_HOME=C:\webdata\gemrepository, when setup.rb reads the value from the Windows registry it gets back c:\\webdata\\gemrepository and the installer bombs out.

Rails

Install using the command line (took about 15mins)
c:\> gem install rails --include-dependencies
I found that because of the firewall within which I sit I had to install the Microsoft Firewall client (which is actually a proxy client) on the server so that the gem download would work.
The web mentions using the -p switch for gem and setting the proxy that way but I couldn't get it working [I didn't try too hard though]

Create Basic Rails application

Create the basis of a rails application.
At the command line run rails path/to/your/new/application I used
c:\> rails C:\webdata\examplesite\app1
This is my [rails app root] = C:\webdata\examplesite\app1

Create a website

You don't need to do this because ROR4IISFCGI does it for you - in my case I lett the ROR4IISFCGI installer create a new site on an existing IIS installation that had several websites already configured.

ROR4IISFCGI

This is an automated installer for getting fast-cgi, rails and SQL server access running under IIS [ http://www.codeplex.com/RORIIS ]
I installed version 1.0.2, which includes Shane Careveo's Fast-CGI ISAPI filter, Ionic's Rewrite ISAPI filter, Ruby FCGI bindings and IIS scripts.
The installer requires that you know
  • the ruby install directory
  • the initial [rails app root] /public directory location
  • iis setup, you need to know a website name where you want to store the log files
  • Fast-CGI setup, I used the defaults further configuration is possible in the registry HKLM\Software\fastCGI\.fcgi
  • Rails for Fast-CGI setup, number of threads etc
Installer steps:
  1. Agree to the terms
  2. check the Rails and SQL support options
  3. Choose to configure IIS with the installer wizard
  4. Enter the website name to be used by IIS , the [Rails app root] /public location (for me C:\webdata\examplesite\app1\public ) , and the log file location (I used the default)
  5. FCGI configuration comes next, I left this at the default
  6. Install location I left as the default (c:\Program Files\RailsForIISFCGI\) Remember this location you will need it later in the process.
  7. A command line window comes up and does some of the install, when prompted by the text in the command box click any key
  8. Click next on the installer window
  9. Click finish
I then opened up the IIS MMC and remove anonymous access to the new site (right click site / properties / home directory / configuration)
I then added index.html to the Documents tab
I then checked for quote marks around the isapi_fcgi.dll entry - because during my testing it had caused an fast cgi server error
You can check this value by using the IIS MMC , right click the site / select properties / click home tab / click configuration button / click the ISAPI mappings tab / scroll down to .fcgi, select it and click edit.
If the reference to the isapi_fcgi.dll file location has quote marks around it remove both of them.

The most useful file that the ROR4IISFCGI installer puts on your server is the following. Look at it if you have trouble after the install
c:\Program Files\RailsForIISFCGI\Documentation\IIS_Configuration.html

Application setup


Create database

I already had a database I created earlier. It contained a single table, the calls table.

database.yml

Edit the [rails app root] /config/database.yml so that it can connect to your database - we use SQL server so my settings are as follows [change them to ones that suit your situation]
production:
adapter: sqlserver
database: mydatabasename
username: sqldatabaseusername
password: pwdforsqluser
host: sqlservernameandinstancename
NOTE be very careful that spaces at start of line and after the colon are correct!
NOTE To test that the database with this username and password is available from the IIS server I create a text file on the desktop, then rename it to a .udl file. Double click the file and you get the ability to enter the database connection information and test the connection.

boot.rb

I got errors in the next section so I had to edit the boot.rb and change require_gem to gem, then save boot.rb
During my second round of testing I didn't have to do this - worth checking though.

generate

In the [rails app root] run the following command line commands
  • ruby script/generate model call
then
  • ruby script/generate controller call

call_controler.rb

Open and edit this file which is in [rails app root] /app/controllers
Edit it so that between the class and end lines it contains
scaffold :Call
Save the file

Action Controller Request.rb (required for IIS)

The c:\Program Files\RailsForIISFCGI\Documentation\IIS_Configuration.html page contains an Action Controller request heading.
Below it is a diagram of the http request flow through the IIS >> ISAPI ReWrite >> Fast CGI >> Ruby >> Action_Controller_Request_ext.rb >> Rails Application
This diagram was VERY VERY useful to me for getting my head around how the whole system hangs together.

[rails app root] /lib

Check that the following files exist
  • [rails app root] /lib/action_controller_request_ext.rb
  • [rails app root] /lib/active_record_sql_server_connection_adapter_ext.rb
If they don't exist copy them from c:\Program Files\RailsForIISFCGI\Files to the [rails app root] /lib folder
More information on these files is here
Action controller request - http://www.codeplex.com/RORIIS/Wiki/View.aspx?title=Documentation%20For%20Modifying%20The%20request_uri%20Method

Environment.rb

Edit [rails app root] /config/environment.rb so that at the end of the file contains
require 'action_controller_request_ext.rb'
require 'active_record_sql_server_connection_adapter_ext.rb'

Testing single app

Theoretically everything will now work and you should be able to access the rails applications you've setup using the appropriate URLS via IIS.
In my case to test I used the following URL
http://localhost/call/list
I found that IIS often didn't give me any useful error messages, but that running up the WebRick rails web server gave me a enough to find my way through any problems that came up.
To start WebRick use the command line to go to your [rails app root] then type
ruby script\server
Now this only allows you to check that the RAILS side of things is working, but at least that meant I had fewer things to look for problems with.
At this point things weren't so good for me
Using IIS I got 'server error, unable to connect to fastcgi server.' http://localhost/call/list
Using WebRick everything was working fine, every row was listed http://localhost:3000/call/list
So I set about checking permissions

Permissions

Using the IIS_Configuration.html page I applied the permissions they outlined in STEPS 5 and 6 there but used a group I had created rather than individual user accounts. [I'm sure security folks will offer lots of comments on this ;-)]
Just to be sure permissions were OK I created a local computer group called 'Rails-Permissions'.
The members of this group are:
  • computername\network service
  • computername\IWAM_computername
I followed the instructions giving read/execute to libfcgi.dll and modify rights to [rails app root] /log and [rails app root] /tmp directories for the 'Rails-permissions' group I created.
I then ran iisreset at the command prompt and tried the IIS test URL again
http://localhost/call/list
Everything worked fine after doing this

The next job is to get multiple apps working under the same website.
NOTE : Generally I found that the first time I accessed a RAILS url the response was very slow, but subsiquent requests from the browser got very quick responses.

Create a second rails app

At the command prompt navigate to where you keep all your rails apps are ( I navigated to c:\webdata\examplesite\ ) and type
rails mynewappname
I ran the following command
rails app2
This created a second rails app for me in the following location c:\webdata\examplesite\app2

I then followed the instructions above from 'application setup' through to 'permissions', excluding the 'testing single app' section

For my purposes I pointed app2 at the same database as my previous application app1, this was just for testing after all.
I tested the app2 site using WebRick and it worked fine, telling me RAILS was OK, now I just had to get IIS to understand what to do.

Getting both apps working on the same IIS site was my next job.

Making Multiple apps work on the same IIS website

Again the C:\Program Files\RailsForIISFCGI\Documentation\IIS_Configuration.html page and it's diagrams were exceptionally useful in helping me get my head around what to do next.
The key was to focus on the ISAPIReWrite4.ini file which is in the c:\windows\system32\inetsrv directory.

For lots of reasons I didn't want to go down the Reverse Proxy route of resolving this issue so I stuck with ISAPIReWrite.

ISAPIReWrite4.ini

You'll find this file here
c:\windows\system32\inetsrv
Edit this file so that redirection to each applications dispatch.fcgi goes to the correct dispatch.fcgi.
What does this mean ?
My goal was to allow multiple rails applications to work in an IIS environment using Fast-CGI.
To illustrate how I've done this you need to know my environment.
I created 2 rails apps (see steps above on how to do this)
C:\webdata\examplesite\app1
C:\webdata\examplesite\app2
I opened the IIS MMC and changed the website home directory from
C:\webdata\examplesite\app1 - it had been set to this by the ROR4IISFCGI setup wizard
to
C:\webdata\examplesite
Now I needed to get the ISAPI ReWriter to understand that there were two different locations it should redirect to under different circumstances.
I opened up the IsapiReWrite.ini file and edited it to contain the following
#>>> Changes to this file require IISRESET to be run from the command line
IterationLimit 0
RewriteRule ^/app1([^.]+)$ /app1/public/dispatch.fcgi?opnq=$1
RewriteRule ^/app2([^.]+)$ /app2/public/dispatch.fcgi?opnq=$1
What these two rules do is convert URLS into calls to the appropriate dispatch.fcgi.
The app1 rule does the following:
  • Browser goes to http://mysite/app1/call/list
  • IIS gives /app1/call/list to the isapirewrite dll
  • the isapirewrite dll receives /app1/call/list and checks it against it's rewrite rules. If it matches one of them it rewrites it.
    Because this URI does match one of the rules the isapierewrite dll passes the following back to IIS /app1/public/dispatch.fcgi?opnq=/call/list
  • Because of the .fcgi in the URI IIS then passes /app1/public/dispatch.fcgi?opnq=/call/list to the fast-cgi isapi filter - NOTE this is the app1 dispatch.fcgi
  • dispatch.fcgi passes opnq=/call/list on to rubyw.exe which passes it on to the action_controller_request_ext.rb within the app1 [rails app root] /lib folder
  • action_controller_request_ext.rb removes the opnq= portion of opnq=/call/list and passes /call/list to the Rails application app1.
  • The Rails application app1 will then render the correct html to the browser.
I found getting my head around this process, and understanding the isapirewrite filter's regular expression syntax were the key's to solving the problem I had.
At this point I ran the iisreset command at the command prompt to reload the IsapiReWrite.ini file.
Then I started testing.
NOTE : changes to the ISAPIReWrite.ini file require that you restart iis for the ini file to be reloaded. If you don't do this you won't see a change in the functionality.
To do this from the command line type iisreset
This will also recycle the rubyw.exe processes.
Note : this may or may not be an issue but one of the other isapi rewrite providers says that all apps using the rewrite dll must be in the same application POOL! http://www.isapirewrite.com/docs/#iis6notes This will mean something to those of you who run IIS in a production environment, or who want to do some googling.
The rewrite dll that I've used is the following http://cheeso.members.winisp.net/IIRF.aspx which may or may not have this problem.

Testing multiple apps

Theoretically everything will now work and you should be able to access the rails applications you've setup using the appropriate URLS via IIS.
http://localhost/app1/call/list
http://localhost/app2/call/list

Some Error messages and debugging

I found that IIS often didn't give me any useful error messages, but that running up the WebRick rails web server gave me a enough to find my way through any problems that came up.
To start WebRick use the command line to go to your [rails app root] then type
ruby script\server
Now this only allows you to check that the RAILS side of things is working, but at least that meant I had fewer things to look for problems with.

Routing error that contains opnq=

in my situation meant that I had not configured the isapirewrite.ini regular expressions correctly

Cannot connect to the fast-cgi server

in my situation this error was resolved by removing the quote marks around the reference to the fast cgi dll location within IIS's ISAPI filters 'executeables' text box, on the 'Add/Edit application extension mapping' dialog box (see note above).

First hit on ruby app CPU 100%

in my situation the first time after an iisreset that a ruby app has a browser access it puts the CPU of the server to 100% and means the browser load time is 4 - 10 seconds, after that response times are very quick. I don't know why this happens.

Adding apps to a working IIS website

To add additional apps to the same website under IIS , isapi rewrite and fast-cgi I use the following steps.
  1. Setup the database for the app - follow the guidelines regarding plural table names etc related to Rails and Ruby
  2. At the command prompt navigate to where you keep all your rails apps and type
    rails mynewappname
  3. Edit the [rails app root] /config/database.yml with the correct connection information, be careful with spaces and the location of the colon in each line (see above)
  4. Edit the [rails app root] /config/boot.rb and replace require_gem with gem (you may or may not have to do this)
  5. Add the following files to [rails app root] /lib/
    action_controller_request_ext.rb
    active_record_sql_server_connection_adapter_ext.rb - only if you need SQL connectivity
    They should be available from C:\Program Files\RailsForIISFCGI\files
  6. Generate the models for the application. Navigate to the [rails app root] and type
    ruby script\generate model dbtablenamesingular
    where dbtablenamesingular is the singular of the plural table name e.g. table in db is calls then you would use ruby script\generate model call
  7. Do this for all models
  8. Generate the controllers for the application. Navigate to the [rails app root] and type
    ruby script\generate controller dbtablenamesingular
    where dbtablenamesingular is the singular of the plural table name e.g. table in db is calls then you would use ruby script\generate controller call
  9. Edit the [rails app root] /app/controllers/dbtablenamesingular_controller.rb files so that they contain the following line
    scaffold :dbtablenamesingular
    Edit the ISAPIReWrite.ini to take account of the new application you've just created (see above for examples), allowing you to have multiple rails apps on a single IIS website
  10. go to the command line and enter
    iisreset
  11. test your new application. The scaffold :dbtablenamesingular code means you'll be able to see a list of the table contents using the following URL without any further coding http://myserver/mynewappname/dbtablenamesingular/list Translate this into whatever your URL should be

ADO.rb

Is automatically installed by the ROR4IISFCGI installer I believe - if you want to check that it is the latest version of ADO.rb then you can do the following:

Download ruby-dbi (dbi-0.1.1.tar.gz) from http://rubyforge.org/frs/?group_id=234&release_id=6448
Use a GZ extraction tool like 7zip ( http://www.7-zip.org/ ) to extract the ruby-dbi folder.
I put the ruby-dbi folder here
c:\webdata\ruby-dbi

Then follow the instructions on the following page
http://wiki.rubyonrails.org/rails/pages/HowtoConnectToMicrosoftSQLServer
copy the ado.rb from c:\webdata\ruby-dbi\lib\dbd to c:\webdata\ruby\lib\ruby\site_ruby\1.8\DBD\ADO

Credits

I hope this has been useful to you I would like to thank all the folks that put up information on this topic that got me to the point where I was able to get multiple Ruby on Rails applications working on a single iis website.

Comments

Unknown said…
Hi dorjem, nice work on the write up, thanks for the props :)

Look for more changes to my RORForIISFCGI installer package in the near future. Things like x64 Server 2003 support, application pool identities, etc.

FYI, you can also create multiple rails apps side-by-side under IIS without using virtual directories and adding the additional rewrite rules (if you need different IIS app pools for each rails application).

I will add myself a note to document this procedure.

Let me know if I can help out!
Brent
Dorje McKinnon said…
Hi Brent
Look forward to the updates on RORForIISFCGI.

In my case I didn't use Virtual directories within IIS. As you say the rewrite rules took care of that.
I have
C:\webdata\examplesite\app1
and
C:\webdata\examplesite\app2
and the IIS site is looking at the following for the home directory
C:\webdata\examplesite\
So the URLS I use are
http://mysite/app1/object/action
e.g. http://mysite/app1/calls/list

Look forward to your note about this

Dorje
Anonymous said…
your rewrite works when trying to get to the app but the app still believes that it is in the web root \\website.com as opposed to \\website.com\app1. All the links and redirects within the app will break.
Murray Speight said…
Thanks dorjem, for this article, It was of great help.

I have detailed my expreiences, with an overview of why you need to do the things you do, This can be found at How to: Run Multiple Rails Apps under IIS using fast Cgi
(Ps: It also includes tips on detecting permissions issues)

Popular posts from this blog

Yammer and puddles

Recently I was asked " What are the top 10 points you think are important to get across to staff at all levels in an organisation about Yammer? " My initial reaction was "Tough ask", mainly because I've seen great write ups on what organisations get out of Yammer but very few that talk directly to the user benefits. Many articles give the usual cop out "users can't see the point, until they get it" I admit I was in that boat when I started using Twitter, a public micro blogging platform. But just like they said "once I used it I got it". What they didn't say was that it took a while and it suits certain people better than others. So as with all things in the social media space, be aware that culture change not the technology may be your biggest challenge. So what does Yammer, a microblogging platform for organisational use , do for real employees that is compelling enough for them to spend the time to "Get it" ? First off Y

Role Title on profiles

Today one of the people I follow on Twitter asked the following question. @ChristySeason Asking all #intranet tweeps: Does your company publish employees' titles on your employee directory/look up/phone book? In following Intranets Live I've been lucky enough to see some great intranets. As such I was able to reply to Christy with the following Nokia do Deloitte do (see the end of the post) Christy's question also prompted me to document my own intranet's profile page. The following image is from the view other's get of my profile. When I look at my profile I see every item that is recorded. I'll save you from that, another post perhaps, if you're interested. DorjeM PS a couple of Vendors I've been reminded of, thanks Crhis and Carolyn, also have screen shots of their profile pages on the web: ThoughtFarmer - intranet software - slideshow of screen shots and Intranet connections - software solution