Rails on IIS revisited

January 24th, 2006

Update: Brent Heinz has written an installer to automate this.

Last time I wrote about setting up Rails on IIS I was in a bit of a rush. However, this time, hot on the heels of an installation on a live customer site, on Windows Server 2003, I have decided to rewrite the original article.

The process I’ve followed here has worked on IIS on Windows 2000 Server, Windows XP and now Windows Server 2003. I don’t know which versions of IIS were involved but the same basic process has been used across all three. I’ve not quite managed to get web services working over IIS but I reckon I’m not far away – so follow the instructions below and I’ll update you when we get there.

So where do we begin? First of all, collect all your bits and bobs together. In particular you will need

Ruby is for obvious reasons.

Rails is useful as I found that 2003 is so locked down that gem did not have access to download the framework from rubyforge.

The DBI-ADO interface is needed for a single file, ADO.rb, that allows the SQL Server adapter to connect to MS-SQL.

Ruby for IIS does some patching to Rails and Ruby to allow IIS to route its requests to FastCGI and eventually to Rails. In the interests of full disclosure I should say that I have not looked at the source of this and so do not know exactly how it works. I will get round to it, promise.

FastCGI keeps a number of Ruby/Rails processes running within IIS. This means that when a request comes in from a client you do not need to start a new Ruby process (and hence incur the not insignificant cost of loading all the libraries) every time. Instead FastCGI starts N processes and if all are busy will start more, upto a maximum of M processes and routes requests to whichever process is free.

The Ionic Rewriter takes a Rails-friendly url (controller/action/id) and rewrites it into a form that IIS understands. IIS then dispatches this new URL to FastCGI which in turn passes it to Ruby.

So, you’ve installed Rails (into C:\Ruby) and copied your application files over (into D:\MyApp). You’ve added the Rails framework into your application’s vendor folder (D:\MyApp\vendor) – this is because we will be altering some of the framework files so we want to keep our changes (in D:\MyApp\vendor) separate from the main Rails installation (in C:\ruby\lib\ruby\gems\1.8\gems). You then need to extract ADO.rb from the DBI file and place it in C:\ruby\lib\ruby\site_ruby\1.8\DBD – you will need to create an ADO folder and place the file into there.

Next up, edit your application’s configuration file (either one of the environment specific ones, or your general one – you decide) and add the line:

ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:tmpdir] = 'D:\\Temp\\'

. You will need to create a Temp folder on D: or your application will silently fail to work. The point of this is to force Ruby to place its session files into a known folder – if you read back through this blog you will find that at one point I was having strange behaviour with sessions. It turns out that as you run under different configurations (CGI, FastCGI and WEBrick) Ruby sometimes places its files in different locations and you get unpredictable behaviour. Plus it also helps when you need to clean up your sessions (which you will need to do later).

Now run your application under WEBrick. This is vital. If it doesn’t work here it definitely won’t work under IIS. Don’t say I didn’t warn you. What? It didn’t work under WEBrick. I bet you forgot to edit your database.yml file. Go and do it now and test it again. Still doesn’t work? Seems to fail silently with no entries in your log file. I told you – create a D:\Temp folder and you should be OK.

Copy your ISAPI files to a safe place – I tend to put them in C:\InetPub – they are associated with IIS but not available to the public. This means copying your FastCGI.DLL and IsapiRewrite4.DLL and IsapiRewrite4.INI files to wherever. Watch out, the Ionic Rewriter DLL and INI file must live in the same folder.

Fire up the trusty pain-in-the-arse Internet Information Services configuration manager. The instructions here are for setting up one site on the “Default Web Site” – I don’t think it will be too hard to set up multiple Rails sites on one IIS site and even easier to set up multiple IIS sites, each containing a single Rails site. But I’ve not done it so I won’t go on about it here.

Right-click on your “Default Web Site” and select “Properties”. Select ISAPI Filters. Click Add and enter a filter name of “Rewriter” and select the IsapiRewrite4 DLL.

Next, switch to the “Home Directory” tab. Make sure “a directory stored on this computer” is selected and set D:\MyApp\Public as the local path. Put your application name into “Application Name” (if this is greyed out then click “Create” to set up the site as an application) and make sure “Scripts and Executables” is selected for “execute permissions”. Next up, click “Configuration”. Under “Mappings” click “Add” and select FastCGI.DLL as the executable, .fcgi as the extension (if you are going to have multiple Rails applications on a single server you need to vary this extension on a Rails-application-specific basis – for example .myapp1, .myapp2 etc), with “All Verbs”, “Script Engine” and “Check that file exists” all selected.

If you’re on Server 2003 there is an extra step. You have to allow IIS access to the executables you are going to be using. Create a new Web Server Extension in the IIS Configuration Manager, calling it “MyApp”. Add FastCGI.DLL, IsapiRewriter4.DLL and RubyW.exe to this extension and make sure that it is enabled.

Phew – what have we done so far?

  • We’ve installed Rails and our application and made sure it works OK under WEBrick
  • We’ve told IIS that the default web site for this server is our application’s public folder
  • We’ve told IIS that any request to the default web site should be fed through the Ionic Rewriter
  • We’ve told IIS that any request for a .fcgi file should be fed through FastCGI

What we’ve not done is tell Ionic or FastCGI how to behave.

Ionic first. Edit IsapiRewrite4.INI – get rid of the contents of the file and replace it with

# Ruby on Rails
IterationLimit 0
RewriteRule ^(/[^.]+)$ /dispatch.fcgi?$1

This takes the URL that IIS recieves and matches it against the given regular expression. I’m no grexpert but I’m reliably informed that it matches any string starting with a ‘/’ that does not contain ‘.’s. If you are setting up a web-service then this has an implication – by default Rails makes the WSDL available via a URL ending in service.wsdl. You will need to edit D:\MyApp\config\routes.rb to change this to something like service_wsdl – otherwise the URL rewriter will spot the ‘.’ and will not feed the request to Rails at all. (Of course, I haven’t got web services working with these instructions yet but I will. Oh yes, I will). Anyway, so it matches any URL starting with a ‘/’ and not containing a ‘.’ – and rewrites it to /dispatch.fcgi?$1. So /controller/action/id will be matched to /dispatch.fcgi?/controller/action/id.

Hang on – our URL is being rewritten with a .fcgi in it – ring any bells? That’s right, next up we configure FastCGI. Open RegEdit and open the Local Machine/Software key. Create a key (folder) called “FastCGI”. Under here create another key (folder) called “.fcgi” – when FastCGI is invoked with a file extension of .fcgi it will use the settings in this key. This is why, when we have multiple applications on a single server, we need to vary the file extensions (.myapp1, .myapp2 as detailed above – likewise we need to rename dispatch.fcgi to dispatch.myapp1/dispatch.myapp2 for each respective application). The basic FastCGI setttings we need (we’ll add some more later) are:

  • AppPath – set this to C:\ruby\bin\rubyw.exe
  • Args – set this to D:\MyApp\public\dispatch.fcgi
  • BindPath – set this to MyAppRailsCGI

. AppPath tells FastCGI that we want Ruby (the “windows” version that does not produce a command line output) to execute our scripts, passing it the Args (our dispatch.fcgi script) as the entry point to the application, using the Named Pipe “MyAppRailsCGI” to communicate.

Now, use the IIS Configuration thingy to restart IIS – right-click on the Server, select All Tasks and restart. This seems to take forever on Server 2003. Now open your favourite browser and point it at your application (http://myserver/controller/action/id or whatever). Now I’m betting that you get a “recognition failed for dispatch.fcgi”.

Let’s take a walk on the dark side. I’m not 100% sure what is going on here. It involves regular expressions and environment variables that I can’t access in debug mode and it all seems to happen before Rails’ logging is invoked. So this is guesswork that seems to be effective (apart from web-services, which, as I have said before, I will return to some other day). Go to D:\MyApp\vendor\actionpack-version\lib\action_controller\request.rb – this is the Ruby file that ActionPack uses to route URL requests. Under Apache and WEBrick, it returns the REQUEST_URI environment variable, and if it can’t get at it, it manipulates PATH_INFO and SCRIPT_NAME to get the same result. Under IIS it doesn’t work – what the method is expecting is a “SCRIPT_NAME” of “/dispatch.fcgi” (which is what we have) but a “PATH_INFO” of “/dispatch.fcgi/controller/action”. In other words, instead of extracting the original URL and making it into a query string, it expects the original URL to be tacked onto the end of the dispatcher script. The problem with this is that if the URL looks like that, then the URL no longer ends with .fcgi so IIS does not know to ask FastCGI to process the request. Our PATH_INFO looks more like “/dispatch.fcgi?/controller/action” – note the all important question mark in the URL. However, if we modify the request_uri method in request.rb to look like:


# Returns the request URI correctly, taking into account the idiosyncracies
# of the various servers.
def request_uri
if uri = env['REQUEST_URI']
(%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri.
else # REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME
script_filename = env['SCRIPT_NAME'].to_s#.match(%r{[^/]+$})
uri = env['PATH_INFO']
uri = uri.sub("#{script_filename}", "") unless script_filename.nil?
uri <<>

I’m 99% sure that this edit is what is making the web-services fall over. However, it does mean that traditional sites (that don’t use query strings) are routed correctly.

Restart IIS (again .. yawn) and try connecting once more. After a long pause (as FastCGI invokes Ruby for the first time) you should see your application. Congratulations. Have a cup of tea.

Now to reconfigure FastCGI again … reopen RegEdit and move to your .fcgi key. Add entries for StartServers (DWORD), IncrementServers (DWORD) and MaxServers (DWORD). This tells FastCGI how many copies of Ruby to start initially (I tend to use 5), how many to start at times of high load (I tend to use 3) and the maximum number of Ruby processes to have running at one time (15 if your server can handle it). I also tend to set the Timeout (DWORD) to 600 – if FastCGI needs to start extra Ruby processes it will keep them alive for ten minutes before shutting them down again. And your last one – add a BINARY key called Environment – and type in RAILS_ENV=PRODUCTION for the value. In Regedit you can directly enter the value for binaries by typing in the right hand side of the edit box – you don’t need to convert each character into Hex, like I did the first time I was confronted with this editor!

And there you have it. Your Rails application (sans web-services) should be up and running on your IIS server. It should have 5 concurrent Ruby processes dealing with incoming requests, increasing to 15 processes under load.

Hope that helps … enjoy.

Oops – almost forgot. Create a batch file (D:\MyApp\Scripts\cleanup.cmd) that contains the line del D:\Temp\Ruby_Sess*.*. Then add a scheduled task to run that batch file every night at some god-forsaken hour. This cleans up Ruby’s session files and prevents too many from being created. Of course, ideally, you would examine the last-changed-time and only delete those that hadn’t been touched in twenty minutes, or whatever, but, for my application at least, getting rid of all of yesterday’s sessions is good enough. Your mileage may vary.

If you find this useful then please take a look at some of my other writing – or recommend me on Working with Rails. Cheers.

55 Responses to “Rails on IIS revisited”

  1. Erwin Quita - [email protected] Says:

    Hi,

    Glad to have found this site… I want to setup ror on windows using iis and was trying it out following your advice and steps… however I have a problem downloading “ruby for iis” because their site is down. If you can send me the installer please do… any help would be appreciated.

    my email is: [email protected]

    many thanks,
    Erwin Quita

  2. Anonymous Says:

    Is it possible to have some ruby on rails apps and also asp.net apps running on the same server?

  3. Baz Says:

    I don’t see why not – the rewriter rule passes any URL without a . in it to Ruby but leaves any URL with a . in it to IIS to deal with. As ASP.NET pages all end with .aspx (or .asmx) the rewriter should ignore those and IIS should route them to the ASP.NET processor.

  4. Steve Says:

    Hey Baz!

    Thanks for writing this.

    How stable is Windows when configured to run with IIS like this?

    Other sources recommend against running Rails on Windows, but you have actually done so for customers in production.

    Does it run just fine, or would you recommend going with a *nix server instead?

    Thanks!
    -Steve-

  5. Baz Says:

    part of the reason i’m doing this is because it’s only a minor part of our application and they are relatively low volume sites. of course if all goes well then more of the application will be built using Rails (an article to come soon enough) and i’ll roll it out to larger customers.

    but, so far, all seems to be going well.

  6. Erwin Quita Says:

    Baz,

    Could you post your working environment please. I’m still having problems making ror work in iis. btw here’s mine.

    Ruby version 1.8.4 (i386-mswin32)
    RubyGems version 0.8.11
    Rails version 1.0.0
    Active Record version 1.13.2
    Action Pack version 1.11.2
    Action Web Service version 1.0.0
    Action Mailer version 1.1.5
    Active Support version 1.2.5
    Application root D:/mailer
    Environment production
    Database adapter postgresql

    windows XP sp2
    iis 5.1

    thanks

    Erwin

  7. Baz Says:

    On my Dev box:
    XP SP2 and IIS 5.1
    Ruby 1.8.2,
    Gem 0.8.10,
    Action Mailer 1.1.5,
    Action Pack 1.11.2,
    Action Web Service 1.0.0,
    Active Record 1.13.2,
    Active Support 1.2.5,
    FXRI 0.3.2,
    FXRuby 1.2.6,
    Rails 1.0.0,
    Rake 0.7.0,
    Application Root: C:\Rails\MyApp
    Ruby in C:\Ruby
    Session files into C:\Temp\Ruby\Dev or C:\Temp\Ruby\Production
    using the SQL Server adapter in ADO mode.

    The customer sites (which I don’t have access to at the moment) were Server 2003 but I deliberately used the same configuration as above for all the Ruby/Rails stuff.

    I guess this is why they say it’s not ready for production Steve – I’ve followed this process on a number of dev boxes and on live sites and not had a problem. I suppose that it’s one of those when where it goes wrong it goes proper wrong!

  8. Chris Lang Says:

    Hi –
    Here is a solution I hacked together quickly to restore query string functionality:

    Replace request_uri with:
    def request_uri
    if uri = env['REQUEST_URI']
    (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri.
    else # REQUEST_URI is blank under IIS – get this from PATH_INFO and SCRIPT_NAME
    script_filename = env['SCRIPT_NAME'].to_s#.match(%r{[^/]+$})
    uri = env['PATH_INFO']

    uri = uri.sub(“#{script_filename}”, “”) unless script_filename.nil?

    parts = env['QUERY_STRING'].split(“*”)
    if parts.length > 1
    env['QUERY_STRING'] = parts[1]
    uri = parts[0]
    else
    uri < < env['QUERY_STRING'] unless env['QUERY_STRING'].nil?
    end
    uri
    end
    end

    THEN modify your rewrite rule too look like this:
    # Ruby on Rails
    IterationLimit 0
    RewriteRule ^(/[^.]*)\?([^.]*)$ /dispatch.fcgi?$1*$2
    RewriteRule ^(/[^.]+)$ /dispatch.fcgi?$1

    This will cause any urls with query strings to have the ‘?’ replaced with an ‘*’. It’s very hackish, but it seems to work well.

  9. [email protected] Says:

    Baz and to all,

    Have you got ror working on iis using Ruby 1.8.4? I compared our working environment and it seems that it’s the only difference in our setup. I am able to see the new welcome aboard screen on my browser when I open my web app.

    thanks,

    Erwin Quita

  10. [email protected] Says:

    ooopss forgot the other details…
    I am able to see the welcome aboard on my browser but could not get the application environment when I try to click the link… and also same when I try to view my controller and action it gives me this error:
    “The specified module could not be found.”

    regards,

    Erwin

  11. Baz Says:

    i’ve never tried it with 1.8.4 – i suppose i ought to.

    Thanks Chris, I’ll have a play and update the article .

  12. Chris Lang Says:

    I’ve updated my code:

    def request_uri
    if uri = env['REQUEST_URI']
    (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri.
    else # REQUEST_URI is blank under IIS – get this from PATH_INFO and SCRIPT_NAME
    script_filename = env['SCRIPT_NAME'].to_s#.match(%r{[^/]+$})
    uri = env['PATH_INFO']

    uri = uri.sub(“#{script_filename}”, “”) unless script_filename.nil?
    #we must have our rewrite rule look like
    #RewriteRule ^(/[^.]*)\?([^.]*)$ /dispatch.fcgi?$1*$2
    #It replaces the first ‘?’ with ‘*’
    parts = env['QUERY_STRING'].split(“*”)
    if parts.length > 1
    env['QUERY_STRING'] = parts[1]
    uri = parts[0]
    env['REQUEST_URI'] = uri + ‘?’ + env['QUERY_STRING']
    else
    #if we didn’t have a *real* query string,
    #then set the uri to the query string IIS gives us
    uri < < env['QUERY_STRING'] unless env['QUERY_STRING'].nil?
    env['QUERY_STRING'] = “”
    env['REQUEST_URI'] = uri
    end
    uri
    end
    end

    Basically, we have to also set env['REQUEST_URI'] and env['QUERY_STRING'] to the proper values before we return uri. Now the entire app can use query strings and access the expected REQUEST_URI.
    Try it out and let me know if you have any suggestions.

    BTW: Here are my rewrite rules:
    RewriteRule ^(/[^.]*)\?([^.]*)$ /dispatch.fcgi?$1*$2
    RewriteRule ^(/[^.]+)$ /dispatch.fcgi?$1

  13. erwin quita Says:

    Baz,

    Do you have any progress on using ruby 1.8.4 and rails on IIS? I would like to know if you have any success on setting it up.

    thanks.

    Erwin

  14. Larry Lane Says:

    Amazing tutorial. I’m up and running on Server 2003 with only one minor hitch. The default mapping in routes.rb is not working in IIS. It works fine in WeBrick, where http://www.mydomain.com redirects to a specified :controller and :action.
    Below is my basic routes.rb

    map.connect ”, :controller => “application”
    map.connect ‘:controller/service.wsdl’, :action => ‘wsdl’
    map.connect ‘:controller/:action/:id’

    I could do an old fashioned redirect to a controller but wanted to do it the rails way if possible.

    Any suggestions would be much appreciated.

  15. Baz Says:

    Glad to be of service!

    I’m guessing that your problem is caused by the URL rewriter – it matches any string that does not have a . (period/full stop) in it. However, I do not think it will match the empty string (I’m not too hot on regular expressions so I may be wrong).

    Could you add a new rewrite rule of:

    RewriteRule ^$ /dispatch.fcgi

    to invoke dispatch.fcgi with no parameters?

    Incidentally, the rewrite rule also means you need to change your route for service.wsdl – as it has a . in it it won’t be passed to FastCGI and instead will be passed to IIS. I tend to rename it to service_wsdl.

  16. Larry Lane Says:

    Thanks for the quick response. That didn’t have an affect. I might play around with the rule itslef a little more.

    Could it have anything to do with the IIS default document? If I add index.html to the IIS default document list the rails welcome screen comes up fine. I rename index.html and add dispatch.fcgi to the default list and get nil object errors in dispatch.fcgi.

    Currently I’ve replaced index.html with a redirect page that points to a controller. That works fine. Not the perfect fix, but works.

  17. Baz Says:

    Maybe /dispatch.fcgi /

    so that it is called with a parameter of root …

    although i’m guessing a bit now and haven’t got time to look into it much further … good luck.

  18. Anonymous Says:

    I’m going to set this up for a customer who insists on using IIS (corporate standard blah blah). The thing is they use the integrated security whateveryoucallit so that their users are logged in to the intranet via their windows login. They want to have the same functionality with the Rails app. Is this possible when using this approach?

  19. Baz Says:

    I have no idea if you can pass windows integrated security through to a rails app (although there is some mention of it in the FastCGI readme file).

    I know Rails itself can authenticate against ActiveDirectory by treating the AD as an LDAP server – there is a gem so that ActiveRecord-ifies LDAP entries …

  20. Baz Says:

    The poster above contacted me separately and discovered this:

    http://wiki.rubyonrails.com/rails/pages/WindowsDomainAuthentication

  21. Chad Redman Says:

    Because we have a few places where parameters are passed in the url string, the modifications posted above by Chris Lang were necessary for me (and worked!). My app uses external authentication, which passes back a validation ticket to our rails app as a url parameter. Rails splits the arguments between ampersands, but doesn’t do it at the question mark. Thus, in “dispatch.cgi?/main/login?key1=val1&key2=val2″, the first parameter name gets set to “/main/login?key1″. You can get around this by adding a sacrificial dummy parameter as the first in the query string, but we didn’t have control over how it was constructed.

    I’m not clear on how to move the modified file to the vendor directory. I’ve tried copying both request.rb and the whole actionpack gem into various combinations of app\vendor, app\vendor\rails, app\vendor\rails\actionpack, etc. If I run a system call tracer, I can see that ruby doesn’t have a problem finding or reading the directories, but it still chooses the official installation. I’d rather not worry about forgetting that I edited a source file before doing a gem upgrade.

  22. Baz Says:

    So far I have installed Ruby on the server without rails – therefore the vendor folder was the only place that Ruby could find the Rails files. I’ve never investigated it with both Rails and the vendor folder present … when I get time I will look into it.

  23. Matthew Stephure Says:

    Chad,

    I also ran into this problem, so I setup a before_filter to insert the sacrificial parameter. Hack? Sure. Easy? Yep.

  24. Rodolfo Says:

    Hello there!

    Man, i’m having doubt on where i get the FastCGI.dll arquive…

    You did not mention in which .zip .rar .tar.gz arquive FastCGI is inside of.

    Could you give a clue where it can be?

    Thank you very much

  25. Baz Says:

    I just used the ISAPI binaries (although the readme is in the source archive): http://www.caraveo.com/fastcgi/fastcgi-0.6.zip

  26. Rodolfo Says:

    Hello again!

    Thanks for the previous help!

    But now, i got another one:

    Your tutorial is perfect when i try to configure on Windows XP. I did it on two diferent machines, and it did well on both XP.

    Now, I’m having problems while i try to do your tutorial on Windows 2000 Server. I did all the steps carefully trying to make no mistake. But it did not work, when i click the “About your application’s environment” link, it gives me the following response:

    Server Error, unable to connect to fastcgi server.

    I’ve tryed everything i could. Do you have any clue about solving this problem?

    PS: I’ve noted that although my sessions are configured to be archived to c:\Temp , they are not. My Rails only create the sessions files if i run it through webrick, but IIS don’t.

    Thanks a lot!

  27. Baz Says:

    My immediate reaction is that Ruby cannot start up because of the session files. I’d guess that IIS/FastCGI does not have permission to write to Temp …

  28. Rodolfo Says:

    Hi Baz, its me again. i hope i’m not bothering you…

    Man, i made it!

    I got rails on iis, but on Windows 2003 Server. But now, i want to ask you something:

    is it possible to configure 2 or more aplications on IIS, each one in a different virtual directory?

    if not, how can i configurate 2 or more apps?

    Thanks!

  29. Baz Says:

    Excellent.

    To tell you all the truth I’ve not had the time to do any IIS stuff recently.

    However, I would say that your best bet is to set up multiple web sites on 2000/2003.

    If you are limited to a single site I have, previously, set up multiple rewrite rules with a folder name at the start of the regular expression. In this way you can use the rewriter to route your requests to your separate folders – however, you then need to alter your routes.rb to deal with the extra prefix at the start of the supplied URL.

  30. Rodolfo Says:

    OK, i dit half of it, but…

    it was a little hard to make IIS and Rails understand together those subdirectories.
    OK, i did half of it, but…

    it was a little hard to make IIS and Rails understand together those subdirectories.

    But it still does not work as i wish… it runs only one app per time, according to the ISAPI Filter, i believe. I’ll explain…

    Because IIS config, i can only setup ISAPI filters for the whole WebSite, not for each subdirectory as mappings … and if a setup 2 ISAPI filters (Rewriter1 and Rewriter2), IIS uses the first according to the order list, and then only one of the apps works…

    by the way, i’ve added you to my msn, so we can discuss better. Mine is: [email protected]

    But it still does not work as i wish… it runs only one app per time, acording to the ISAPI Filter, i believe. I’ll explain…

    Because IIS config, i can only setup ISAPI filters for the whole WebSite, not for each subdirectory as mappings … and if a setup 2 ISAPI filters (Rewriter1 and Rewriter2), IIS uses the first acording to the order list, and then only one of the apps work…

    by the way, i’ve added you to my msn, so we can discuss better. Mine is: [email protected]

  31. Baz Says:

    Rodolfo and I have had an email exchange and he got as far as setting up a single Rewriter with two rewrite rules:

    RewriteRule ^/myapp1(/[^.]+)$ /myapp1/dispatch.fcgi1?^/myapp1$1

    RewriteRule ^/myapp2(/[^.]+)$ /myapp2/dispatch.fcgi2?^/myapp2$1

    The applications work but the static files now appear to be served up incorrectly.

    Close but not quite!

  32. Anonymous Says:

    has the ActionController::Base.asset_host setting been set correctly in environment.rb?

  33. Jeff Ward Says:

    I would be interested to see side by side performance tests comparing various Rails setups such as the following.

    1) IIS\FastCGI (Windows)
    2) Apache\FastCGI (Windows)
    3) Apache\FastCGI (Linux)
    4) Apache\CGI (Linux)
    5) Lighttpd\FastCGI (Linux)

    Get the same app running on all.

    If this has been done already, would somebody please post it here. If not, Baz, you should organize this!

    Or for those other bloggers, set this up and it would be sure way to get traffic to your site within the Rails community.

    Jeff

  34. Baz Says:

    Sorry – at the moment I don’t have the resources. Windows only at work, Mac only at home and the only Linux I have access to is a shared hosting account somewhere on a server in California.

    When I get my Intel Mac (he says staring wistfully at the pennies in his pocket) I will do some sort of comparison …

  35. Doug Says:

    I am experiencing the same error as Rodolfo (which he apparently solved) – I’m getting “Server Error, unable to connect to fastcgi server.”

    However, unlike Rodolfo, I haven’t been able to solve it on my own. I have added write permission to D:\Temp for the IIS_WPG group and for the IWAM user in that group with no luck. Any suggestions would be appreciated.

  36. Baz Says:

    Make sure you have Ruby for IIS installed correctly.

    Check your FastCGI configuration for typos in the parameters.

    Make sure that your sessions are configured correctly.

    Make sure you have the MS Visual C runtime DLL installed (http://made-of-stone.blogspot.com/2006/04/getting-weird-fastcgi-errors.html).

    Try running dispatch.fcgi from the command line (move to myapp/public and “ruby dispatch.fcgi /controller/action/id“) – normally it should say internal server error but it may say something else that could help pinpoint the problem.

  37. Rodolfo Says:

    Well, that error: “Server Error, unable to connect to fastcgi server.” I’ve never solve it on Windows 2000.
    On that time I was trying to setup Rails on IIS on a Windows2000 Server. Because it was not my machine, some guy must have changed something on it before, that messed up everything so i could not setup Rails on IIS correctly. (I believe it has something to do with users permissions)

    After that, they’d passed me a new, untouched pc (Windows 2003 Server). Then, your tutorial worked perfectly on the first try.

    Well we’ve gotta know which OS our brother Doug is using.
    Your last comment is a good way to test the FastCGI. Although I usually test my FastCGI via browser, putting on the url: http://localhost/dispatch.fcgi?controller/action
    it should give some answer…

  38. Doug Says:

    I’m on Windows Server 2003. However, I am running multiple sites on the box – one ASP.NET and one regular ASP. The sites share an IP address and are distinguished by a load balancer using ports.

    I have experimented with moving the Ionic Rewriter DLL around. I put it in the D:\MyApp\public directory, along with the INI file, for now.

    Using FilemonNT, I can see that when I try to access the homepage (which returns a Directory Listing Denied error), that the request is being passed to w3wp.exe and that the path is D:\MyApp\public. When I try to request an interior page (like MyApp/events), the request is being passed to the rubyw.exe process and the path is D:\MyApp\public\dispatch.fcgi. This returns the “Server Error, unable to connect to fastcgi server.” error.

    In the IIS log, I see the following:

    #Date: 2006-05-12 19:39:16
    #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
    2006-05-12 19:39:16 [ip] GET / – [port] – [ip] Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 403 14 5
    2006-05-12 19:39:25 [ip] GET /dispatch.fcgi /events [port] – [ip] Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322) 200 0 0

    The fastcgi.crash.log shows the following:

    [12/May/2006:10:53:55 :: 3712] Ignoring unsupported signal USR1.
    [12/May/2006:10:53:55 :: 3712] Ignoring unsupported signal USR2.
    [12/May/2006:10:53:55 :: 3712] Ignoring unsupported signal HUP.
    [12/May/2006:10:53:55 :: 3712] Ignoring unsupported signal SIGTRAP.
    [12/May/2006:10:53:55 :: 3712] starting
    [12/May/2006:10:53:55 :: 3712] terminated gracefully

    When I try running ruby dispatch.fcgi from the command line, I see the code for the 500.html page I have set up.

  39. Baz Says:

    What’s your rewrite rule?

    I think it is splitting the ruby command line into two parts when they need to be glued together with a query string (see Chris Lang’s comments).

  40. doug Says:

    Here’s the contents of IsapiRewrite4.ini (which is in the app/public directory, along with IsapiRewrite4.dll):

    # Ruby on Rails
    IterationLimit 0
    RewriteRule ^(/[^.]+)$ /dispatch.fcgi?$1

  41. Baz Says:

    Sorry Doug, I don’t know. It all looks OK to me …

  42. Doug Says:

    I’m trying to go over your instructions again, and one thing I don’t see (perhaps I’m just missing it) is when to install Ruby for IIS. I don’t know if this matters.

  43. Baz Says:

    You’re right Doug – totally forgot to mention it. You should be able to install it at any time after your Ruby installation. I will update the main article when I get the chance.

  44. Jake Says:

    If you run the following command line from the public folder and get the following error:

    `const_missing’: uninitialized constant RailsFCGIHandler (NameError)

    Then one of the possible error may be that the RubyForIIS installer has placed some files in the wrong folder. Look for a subdirectory called ‘RubyForIIS’ somewhere in the c:\ruby folder. you will need to copy all contents to the C:\ruby\lib\ruby\site_ruby\1.8 folder.

  45. Rodolfo Luz Says:

    Hi there people! I’ve post a portuguese version/adaptation of this tutorial available in my my blog

  46. Anonymous Says:

    Hi,

    I used Rodolfos tutorial and it worked very well.

    I kept getting the dreaded “Server Error, unable to connect to fastcgi server” error. Apparently the user running the IIS instance (IWAM_OTER in my case – OTER is the name of my machine) didn’t have permission to access the following files:

    C:\ruby\lib\ruby\site_ruby\1.8\fcgi.rb C:\ruby\lib\ruby\site_ruby\1.8\i386-msvcrt\fcgi.so

    when I fixed this everything worked.

    Hope this helps someone else.

  47. Anonymous Says:

    Hi!

    thanks for this great howto.
    but currently i’m stuck with a a strange problem involving ajax.

    when trying to update iformations using “link_to_remote” i’m getting the login dialog over and over again, and it won’t let me authenticate there.

    i guess there are more files i need to set proper permissions. but i have no idea on what files.

    anyone else having this problem or even a solution?

    thanks!

  48. Baz Says:

    It’s working OK for none-AJAX links but not for AJAX ones? Strange – not something I’ve ever seen (but I’m not really using authentication).

  49. neongrau Says:

    exactly. all non-ajax links work fine.
    really weird. i’m pretty much stuck now after i even tried giving “everyone” full access to the involved files/direcories as a last resort. (at least all i could imageine, the appdir, sessiondir, even the full ruby dir).

    would be great if you could do a quick check if it works for you by unticking the anonymous access. (provided you have a machine to test with at your hand)

    thanks alot!

  50. neongrau Says:

    just read that MS is currently working on their own fastcgi component.

    see http://www.iis.net/default.aspx?tabid=1000051

    only a technical preview which doesnt look like its ready for rails yet but promising.

  51. Baz Says:

    It would appear that the server I used to test all this FastCGI stuff has been “decommisioned”. It may take me a while to get a new one going. Sorry.

  52. Donald Says:

    I’m trying to get Rails working on IIS 5.1 on WinXP. I’m quite close, I actually have IIS talking to dispatch.fcgi, but I always get rails’ “Application error” 500 message when I hit URLs that map to my rails app.

    Yes, everything works properly in webrick. Note that I also get a 500 when I run dispatch.fcgi from the command-line.

    Any suggestions for routes of attack for debugging this problem?

  53. Baz Says:

    I’m guessing a bit but have you tried the fastcgi permissions thing in one of the comments above?

  54. Brandt Says:

    Just a note for people who are trying to suss out dispatch.fcgi errors. I have Rails running on an IIS5.0/Win2k server and everything works perfectly when I install my rails app locally on a server drive. However, if I install the app on a network drive, it appears that the credentials that allow it to work on the local drive get dropped and cause the infamous “unable to connect to the fastcgi server” error because the system sees the request as anonymous, which our network doesn’t allow.

    I believe this is happening at the rewriter level from some of my research. Some commercial rewriters support the passing along of windows credentials, but I haven’t had a chance to see if that solves the problem for me.

    I know you haven’t had a chance to work on Rails on IIS in a while Baz, but I just wanted to say thanks, it was an excellent helper in my testing.

  55. Murray Speight Says:

    Thanks for the article, this helped heaps.

    I have have detailed my experiences, with tips on finding permissions issues at
    How to: Run Multiple Rails Apps under IIS using fast Cgi