Intro
This is an update to my blog on running rails with IIS and Mondrel using MSSQL, This update details the steps for a rails v2.0 application (rather than 1.8)
My Rails app is not heavely used (2 full time, several casual users), so a proxy/redirect from IIS to single Mongrel seemed ideal.
IIS will still service up the static/public content, and all other requests are forwarded to Mongrel(s). Using ISAPI_Rewrite3 from Helicon Tech
ISAPI_Rewrite3 is cool it mimics Apache mod_rewrite.
Also I needed to re-document the install/set-up so here it is.
Install Software
Overview
- Ruby is installed in C:\ruby
- Rails applications are under C:\rails
- Rails application is called "rapp" (Rails application). And in C:\rails\rapp
- SQL Express is the database.
- A install CD with all relevant software/gems is available on R:\downloads
Install MSSQL
Install MSSQL with a named instance SQL$RAPP this will allow you to shutdown one rails application DB, without affecting others.
> cd R:\downloads
> dotnetfx.exe # Install .Net Frame work 2.0
> SQLEXPR32-SP2.EXE # MS SQl Server 2005 Express with SP2,
Untick "Hide Advanced Options" to allow a named instance to be insalled
# Used Named Instance "RAPP" based on name of rails application
# Used mixed authentication, "sa" passsword "*********"
> SQLServer2005_SSMSEE-SP2.msi # MS Sql Server Managment Studio with SP2
Configure MSSQL
Rails connects to MSSQL using tcp/ip. This is not enabled by default
> SQLServerManager.msc # Start "SQL Server Configeration Manager"
SQL Server Network Configuration -> Protocols for RAPP -> Enable TCP/IP
SQL Native Client Configuration -> Client Protocols -> Enable TCP/IP
Install Ruby
This is included for completeness
> cd R:\downloads
> ruby186-25.exe # Install ruby # source: ruby
# Select Install "Ruby" and "Enable RubyGems"
# Install to "C:\ruby
# Check C:\ruby\bin to your everyones path !!
# If not added, My Computer -> Properties ->
Advanced -> Environment Variables -> System Variables
> cd R:\downloads\rubygems-0.9.4 # source: rubygems
# NOTE: Use 0.9.4 as mongrel does not install correctly with 0.9.5
> ruby setup.rb # Install ruby gems
Install Rails/Mogrel
> cd C:\downloads
> gem install rake # http://rubyforge.org/projects/rake/
Successfully installed rake-0.7.3
> gem install rails # "http://rubyforge.org/projects/rails/
Successfully installed activesupport-2.0.1
Successfully installed activerecord-2.0.1
Successfully installed actionpack-2.0.1
Successfully installed actionmailer-2.0.1
Successfully installed activeresource-2.0.1
Successfully installed rails-2.0.1
> gem install mongrel # pick the win32, # http://mongrel.rubyforge.org/
Successfully installed gem_plugin-0.2.3
Successfully installed cgi_multipart_eof_fix-2.5.0
Successfully installed mongrel-1.1.1-mswin32
> gem install mongrel_service --source http://gems.rubyforge.org # pick the win32
Successfully installed win32-service-0.5.2-mswin32
Successfully installed mongrel_service-0.3.3-mswin32
Install MSSQL Drivers
Install MSSQL Drivers (DBI/ADO drivers)
> cd R:\downloads\ruby-dbi-0.1.1 # http://rubyforge.org/projects/ruby-dbi/
> ruby setup.rb config --with=dbd_ado
> ruby setup.rb setup
> ruby setup.rb install
Install sqlserver adapter (as now packaged seperately) - this is available from http://gems.rubyonrails.org
> gem install activerecord-sqlserver-adapter --source http://gems.rubyonrails.org
Install RMagick / Faster CSV
NOTE: When including rmagic in your rails app. Use the full name rmagic.rb,
as depending on your paths rgagic.so may be included rather than rmagic.rb
> cd R:\downloads\rmagick-1.15.9 # http://rubyforge.org/projects/rmagick/ win32
> ImageMagick-6.3.5-8-Q8-windows-dll.exe
# Install to C:\ruby\ImageMagick
# Tick [x] Update executable search path.
> gem install rmagick-1.15.9-x86-mswin32-60.gem --local
# Note: Documentation is in
# C:\ruby\lib\ruby\gems\1.8\gems\rmagick-x.x.x-win32\doc\index.html
> cd R:\downloads
> gem install fastercsv-1.2.0 --local
Install Iaspi Rewriter
> cd R:\downloads
> ISAPI_Rewrite3_00xx.msi # http://www.helicontech.com/isapi_rewrite/
# Install to C:\Inetpub\ISAPI_Rewrite3\
> Run C:\Inetpub\ISAPI_Rewrite3\Helicon Manager.exe
# And Register product # See: serialno.txt for the serial number
Patch and Patch
Patch Active Record - SQL Server Adapter
SQL 2005 differs from previous versions, it reports null columns as uppercase NULL and you need to patch the sqlserver_adapter.rb
# Patch sqlserver_adapter.rb (See Rails Ticket #7733) for server 2005
> cd C:\ruby\lib\ruby\gems\1.8\gems\activerecord-sqlserver-adapter-1.0.0\
lib\active_record\connection_adapters
> edit sqlserver_adapter.rb
# Line ~304: default = ...... "=~ /null/ ? nil" ==>
"=~ /null/i ? nil" # Case insensitive match on the word
Patch Action Controller - CGI Process
When preforming a re-direct the header is inspected for the real host when request
has been forward, however rails does not strip any extra white space.
> cd C:\ruby\lib\ruby\gems\1.8\gems\actionpack-2.0.1\lib\action_controller
> edit cgi_process.rb
def host_with_port_without_standard_port_handling
if forwarded = env["HTTP_X_FORWARDED_HOST"]
forwarded.split(/,\s?/).last
etc ...
# Line ~87: forwarded.split(/,\s?/).last ==>
# forwarded.split(/,\s?/).last.strip # strip extra spaces/tabs
Patch SQL Server Adapter - to handel dates prior to 1970
This is detailed in a seperate post, Check out
SOLVED: Rails + MSSQL dates prior to 1970
Create/Configure Rails Application
Create Rails Application
> mkdir C:\rails
> cd C:\rails
> rails rapp # Create rails app called rapp
Add in some addins
Active record "acts_as_list" is now a plugin add it in, I also recommend annotate_models from "Agile Developemnt With Rails"
> cd C:\rails\rapp
> gem install acts_as_list --source http://gems.rubyforge.org
> ruby script/plugin install file://C:\downloads\annotate_models
> ruby script/plugin install http:#svn.pragprog.com/Public/plugins/annotate_models
Create Rails "Hello World" Application
> ruby script/generate controller hello
Edit C:\rails\rapp\app\controllers\hello_controller.rb. And past in this code.
class HelloController < ApplicationController
$render_count ||= 0
def world
$render_count += 1
render :text => "<html><body><h1>Hello World</h1>
Page rendered #{$render_count} times.</body</html>"
end
end
Woops: We dont have a database yet, so remove the requirement
Edit \rails\rapp\config\environment.rb
# No database support, remove active_record etc ..
config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
Test basic application works with WebBrick
> cd C:\rails\rapp
> ruby script/server # Run WebBrick to test
> iexplore.exe http://localhost:3000/hello/world
# Should get hello world page
> Ctrl+break # Close WebBrick
Host using mongrel service
Perform the following steps to host rapp using mongrel
NOTE: We will be hosting this rails application under the relative url "/rapp"
NOTE: We only bind to localhost (127.0.0.1), since IIS will eventually forward locally to mongrel
The port chosen is 4004
> cd C:\rails\rapp
> mongrel_rails service::install -N rails_rapp -a 127.0.0.1
-c C:\rails\rapp -p 4004 -e production --prefix /rapp
# NOTE: adding --prefix /rapp, sets
# ActionController::AbstractRequest.relative_url_root = "/rapp"
> sc config rails_rapp start= auto
> net start rails_rapp
# To remove the service use: mongrel_rails service::remove -N rails_rapp
Permissions
Mongrel service will be running as SYSTEM or NETWORK SERVICE, You need to check/give the following permissions.
- Give FULL permission for C:\rails\rapp\temp and C:\rails\rapp\log
- Give FULL permission to TEMP (C:\WINDOWS\TEMP)
- Give FULL permission to any other folders your rails app1 writes to (e.g C:\rails\app1\public\attachments )
- Check Read/Execute permissions for C:\ruby\* and C:\ruby\ImageMagick
- Check Read permission Under HKEY_CLASSES_ROOT\ADODB.Connection for both the ADODB.Connection and ADODB.Connection.X.X entries # mssql only
Test using mongrel service
Browse to http://localhost:4004/rapp/hello/world, Note all url's are now relative to rapp, This allows multiple rails apps to be hosted behind iis
> iexplore.exe http://localhost:4004/rapp/hello/world
# Should get hello world page, Rendered for the 1st time
# Press refresh a few times, See the counter grow.
Now to host behind IIS
Create a virtial directory, so IIS services up the public/static portion of the site, (i.e. C:\rails\rapp\public)
> mkdir C:\Inetpub\Logfiles
> inetmgr.exe # Change log file folder
# Goto -> Default Web Site -> Properties -> Web Site Tab -> Logging properties
Log file directory -> C:\Inetpub\Logfiles
> inetmgr.exe # Add in your application
# Goto -> Default Web Site -> New -> Virtual Directory ->
Alias/Name -> rapp
Directory/Path -> C:\rails\rapp\public
Permissions -> Read + Scripts + Executables
# Note: Need Execute otherwise proxy/forwarding does not work !!!!
Test static portion
Browse to http://localhost/rapp/index.html - You should see the standard welcome to rails page
> iexplore.exe http://localhost/rapp/index.html
# Should get the "Rails Welcome aboard"
Configure ISAPI_Rewrite3 to forward to Mongrel
Confiure ISAPI_Rewrite to forward all http://host/rapp/* to mongrel on http://127.0.0.1:4004/rapp/*.
NOTE: We do not forward requests contining a full stop (.), So files like .js and .css etc will be serviced up by iis
> C:\Inetpub\ISAPI_Rewrite3\Helicon Manager.exe
Click -> Edit
Enter your new rule
RewriteProxy rapp/([^.]+)$ http://127.0.0.1:4004/rapp/$1
Your "C:\Inetpub\ISAPI_Rewrite3\httpd.conf" file should look something like
# Helicon ISAPI_Rewrite configuration file
# Version 3.0.0.23
RewriteEngine on
RewriteBase /
RewriteProxy rapp/([^.]+)$ http://127.0.0.1:4004/rapp/$1
Rails .htaccess legacy
Remove/Rename the c:\rails\rapp\public\.htaccess file,
as this is read by ISAPI_Rewrite but is designed for Apache !!!
> rename c:\rails\rapp\public\.htaccess c:\rails\rapp\public\apache.htaccess
Test mongrel/dynamic portion
Browse to http://localhost/rapp/hello/world - You should see the Hello World with counter from last test
> iisreset # restart iis
> iexplore.exe http://localhost/rapp/hello/world
# Should get hello world page, Rendered for the nth time
Finished
You should now have a working rails application, behind IIS using Mongrel.
To add another application simply nominate a new relative url and repeat the above steps
Multiple Applications
When running multiple rails applications, Set the session key to be unique for each
instance, otherwise you will be trying to share session keys across multiple apps.
> Edit \rails\rapp\controllers\application.rb
config.action_controller.session = {
:session_key => '_rapp_session',
:secret => '571 etc... a0263'
}
Notes on: SSL/HTTPS and ISAPI_Rewrite3 with RewriteProxy
If you are running IIS with SSL, You need to pass to the backend application than fact you are running https://
The header needs to contain "X-Forwarded-Proto: https", ISAPI_Rewrite3 does not add this for you as it does for X-Forward-Host etc.
So we need to do it ourselves if using https
Edit your "C:\Inetpub\ISAPI_Rewrite3\httpd.conf" to contain the following, Before any RewriteProxy
# Add "X-Forwarded-Proto: https" to the header so back end knows if running with ssl/https
RewriteCond %{HTTPS} ^on$
RewriteHeader X-Forwarded-Proto: .* https
RewriteProxy etc ....