For years there's been numerous hacks and ways to get Ruby on Rails to run on IIS. There's also ways to get Java via Tomcat or Jetty, Go, and other languages and environments to run as well. There's ways to get Node.JS running on IIS using iisnode but that's been node-specific. The blog posts you do find say things like "get Rails to run on IIS in 10 steps" and I'm like JUST TEN?!? Why not 13? Others say "You can deploy Rails under IIS, it's just very difficult and there's not a lot of documentation. You'll need a special Fast-CGI implementation...WELCOME TO HELL."
Azure Websites has supported node AND Java (again, Tomcat or Jetty) for a while now, in production and it's very nice and it runs under IIS. How? They've now brought that support to Windows running IIS 8+ with the release of the HttpPlatformHandler. Here's their example on how to get IIS 8+ running Java, easily.
Let's see if this works well with Ruby on Rails as well!
Why is HttpPlatformHandler interesting? Check this from the docs...it means IIS can host anything that runs on Windows now, easily. These things were possible before, but with all kinds of hacks and FastCGI this and that. What's great about HttpPlatformHandler is that it isn't about Rails. It's about any process that's listening on a port. You get all the value of IIS *and* total control of your self-hosting scenario.
The HttpPlatformHandler is an IIS Module, for IIS 8+, which does the following two things:
- Process management of http listeners - this could be any process that can listen on a port for http requests. For example - Tomcat, Jetty, Node.exe, Ruby etc;
- Proxy requests to the process that it manages.
To be clear, you can work with Ruby on Rails on Windows and have it host itself with WEBrick locally, but if you're going to go production on Windows you'll want to have IIS. What value does IIS provide in a scenario like this? Static file hosting, Reverse Proxy, complex auth that can span multiple apps, languages and frameworks, it monitors and manages your process looking at memory and CPU, crashes, etc.
Running Ruby on Rails on IIS 8 with the HttpPlatformHandler
First make sure you have Ruby on Rails. If you do, skip forward.
I use the http://railsinstaller.org for Windows and go. You'll get Ruby, Rails, Bundler, Sqlite, and TinyTDS. Even SQL Server support. Very kind of them. Another good Rails on Windows on is RailsFTW.
I go to Turn Windows Features On and Off to make sure I have IIS installed as well.
Then get the HttpPlatformHandler. You can get it with the Web Platform Installer, or just install it from here: x86/x64
I make a folder for the app I'm going to make. I put it in c:inetpubwwwrootrails but you can move it around if you like.
I right-click my folder in IIS Manager and "Convert to Application."
I run "gem install rails" to make sure I have Rails in the first place. ;) You will if you installed with the RailsInstaller. If you installed with the RubyInstaller, then this will get you Rails.
NOTE: If you have issues with SSL running gem on Windows, you'll need manually to update gem to 2.2.3 as of the time of this writing. I'm not sure why this isn't already done by the installer. The symptom I saw was weird errors on 'bundle install' that was fixed by this.
Then, from inside c:inetpubwwwrootrails, I ran "rails new helloworld." I ended up moving this folder up. I should have just made the app first, then converted the folder to an app in IIS. Order of operations and all that, eh?
OK, now I'll "rails server" from within c:inetpubwwwrootrails, just to make sure Rails can run under the local WEBrick server. And it does:
Now, let's do it under IIS.
I need to make sure there's a web.config file in the same root folder as my Rails app. WHAT?!? Web.config is for ASP.NET, right? Well, no. It's config for any IIS application. You'll need this for Go, Java, PHP, Rails, node, ASP.NET, whatever. IIS can host basically anything.
Lemme add a hello world controller and edit its view. I'll "rails generate controller welcome index" then edit appviewswelcomeindex.html.erb for good measure.
I put my Rails app under http://localhost/rails rather than at the root http://localhost so I did need to tell Rails 4 about the fact it's running in a subdirectory with a change to /config.ru, otherwise my routes wouldn't line up.
Rails.application.config.relative_url_root = '/rails' map Rails.application.config.relative_url_root || "/" do run Rails.application end
Make special note of the paths below AND the encoded " there in the arguments. That's important, because it's a quoted argument passed into the ruby.exe process that IIS will kick off. Note also the %HTTP_PLATFORM_PORT% environment variable reference. That is passed in by IIS and will be a localhost-bound high port.
I also put in foo and bar for theoretical environment variables you might want your Rails app to know about. For example, I might add:
<environmentVariable name="RAILS_ENV" value="production"/>
...when it's time. I put in some standard debug logging there with the "stdout" but you can remove that if you don't want the clutter. Make sure your IISR_ users have write access to the folders if you want to see any logs.
Also, on slower machines when running in development, you might need to up your startupTimeLimit if you are seeing IIS stop your Ruby processes that take to long to startup.
<?xml version="1.0" encoding="UTF-8"?>
<add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
<httpPlatform stdoutLogEnabled="true" stdoutLogFile="rails.log" startupTimeLimit="20" processPath="c:RailsInstallerRuby2.1.0binruby.exe"
arguments=""C:RailsInstallerRuby2.1.0binrails" server -p %HTTP_PLATFORM_PORT% -b 127.0.0.1">
<environmentVariable name="foo" value="bar"/>
Here's a screenshot of Ruby within the SysInternals Process Explorer application. I wanted to show you this so you could see the Process Tree and see who started which process. You can see w3wp (that's IIS) which is a Service, and it's hosting Ruby, running Rails. Make note of the command line arguments as well.
And here it is. Ruby on Rails 4 running under IIS8 on my Windows 8 machine.
Big thanks to Ranjith Ramachandra (@ranjithtweets) at Microsoft for the help with the web.config values!
So, basically, to give you the TL;DR version, except at the end. When you have IIS, install HttpPlatformHandler and add a web.config as appropriate and you're all set. Run what you like, passing in the port that IIS will proxy to.
Sponsor: Big thanks to Infragistics for sponsoring the feed this week! Responsive web design on any browser, any platform and any device with Infragistics jQuery/HTML5 Controls. Get super-charged performance with the world’s fastest HTML5 Grid – Download for free now!
© 2014 Scott Hanselman. All rights reserved.