Ruby On Rails, Thin and Nginx on Windows

Are you like me? Do you work in an industry or business which requires you to write web applications that runs on Windows? It’s not all that bad, right? C# 3.0 and 4.0 are pretty nice languages, and ASP.NET MVC is light years ahead of reguar ASP.NET. At my day job, I’m replacing traditional desktop applications with web applications. These are highly functional engineering applications, but they will have very few users at any one time, so they don’t need to run on a full blown web server. One big problem I run into is that ASP.NET applications are tied to IIS.

There are hardly any good ways to ship an ASP.NET web application as a stand alone product, which is a shame, because there are some impressive web applications which can run stand-alone, with an embedded web server and there should be more. It’s not like deploying ASP.NET applications is a total nightmare, there is something called “Web Matrix” and the commercial Cassini web server, plus the Windows Platform Installer, and even http.sys. Web Matrix, from Microsoft includes the “IIS Lite” web server, a stand-alone version of IIS, but it’s bundled with Sql Server Express, Visual Studio Express and Expression Studio — hardly a stand alone option for shipping a web application. The commercial Cassini server, might, I suppose, be an option, but I can’t tell, without purchasing it, whether it’s robust and up to date. It’s not sold by Microsoft so it might be out of sync with their latest technologies. The Windows Platform Installer has taken much of the pain out of packaging and deploying Windows web applications (except it doesn’t run aspnet_regiis.exe for some reason), so that a product like Umbraco can be installed with just a few clicks. Finally, you have http.sys, an HTTP server built into modern versins of Windows. It will allow Console or Windows Forms application to host WCF services, but will not, as far as I can tell, host an entire ASP.NET website.

This blog post is aimed at software developers, not really managers, but it may help you if you’re a manager trying to understand what some of your best developers are thinking. What are they thinking, you ask? Well, they really are stoked about ASP.NET MVC, at least they were for a while, until they realized it’s just a cheap knock-off of Ruby On Rails. Yes, it’s an MVC framework, that’s good, and even better, most of the code that MS ships is pretty solid, but as far as features, it’s consistently a year or two behind RoR. Good web developers want to work with the best technology, so being stuck in asenior web developer position writing ASP.NET, drives them mad after a while. They can’t leave and take an entry-level position learning Rails. So what can they do?

Enter RoR on Windows. It’s actually solves two problems:

  1. Your company needs to deploy a web application what is easy to install and run on any desktop (think sales guy on an airplane).
  2. Your good web developers want to work with awesome technologies.

I didn’t invent it, obviously, but I have will show you the steps I used to get it running.

First, a few caveats:

  1. All I’ve done so far is pull up the default rails application page, not run a full application.
  2. I want this installation to be able to sit anywhere in the file system, but right now it needs to stay in the same path you create it at, e.g. C:\StandAlone
  3. I’ll update this post as a progress further, hopefully developing a full, stand-alone RoR web app on Windows, which can be deployed by just copying files.

Procedure to Get RoR, Thin and Nginx Running on Windows

  1. Download the latest RubyInstaller for Windows.
  2. Install to C:\[Stand_Alone_Dir]\Ruby, where [Stand_Alone_Dir] is what ever you want to call it. I’ll call it C:\StandAlone for now on.
  3. During the install, do not add Ruby to the system path of register ruby file types, we want to make sure the web application can be installed by just copying a the StandAlone directory.
  4. After the RubyInstaller is finished, check out the properties of the shortcut in the start menu called, “Command Prompt with Ruby.” Notice that CMD.EXE opens setrbvars.bat with the /K flag which tells the command windows to run the batch file and remain open. setrbvars.bat uses the %~dp0 variable which stores the directory in which the batch file resides; in this case, it’s the Ruby bin. This little bit of DOS magic will be useful for other scripts.
  5. Download the DevKit from RubyInstaller.
  6. Extract it to C:\StandAlone\DevKit.
  7. Open a Ruby command prompt and CD to C:\StandAlone\DevKit. Run ruby dk.rb to generate the config.yaml file.
  8. Run ruby dk.rb install.
  9. gem install thin –platform=ruby
  10. gem install rails –platform=ruby
  11. Download the Sqlite shell (sqlite.exe) plus the Sqlite Dll for Windows and place them both in C:\StandAlone\Ruby\bin.
  12. gem install sqlite (or gem install sqlite3-ruby for for rails2) (notice here, we don’t use –platform=ruby. I don’t know why, but using the –platform=ruby flag here caused a lot of errors. These gem installations seems to be very smart about knowing if you’re running on a Windows platform, but the DekKit documentations is adamant about using the –platform=ruby flag to avoid downloading binaries for other platforms. )
  13. MK DIR C:\StandAlone\www
  14. CD C:\StandAlone\www
  15. rails new mystandalonewebapp.com
  16. Test out with, thin start
  17. Download Nginx binary for Windows and put in C:\StandAlone\nginx
  18. Create two folders: C:\Standalone\nginx\sites_available and C:\StandAlone\nginx\sites_enabled
  19. Create a file, mystandaloneapp.com.txt in sites_enabled.
  20. Copy C:\Standalone\nginx\conf\nginx.conf to nginx.conf.orig.
  21. Edit nginx.conf to look like:
    worker_processes  1;
    error_log  C:/StandAlone/nginx/logs/error.log;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        sendfile        on;
        #keepalive_timeout  0;
        keepalive_timeout  65;
        #gzip  on;
        include C:/StandAlone/nginx/sites_enabled/*.txt;
    }
    
  22. Create a file, C:\StandAlone\nginx\sites_enabled\mystandaloneapp.com.txt to look like:
    upstream mystandaloneapp {
    	server 127.0.0.1:3000;
    }
    
    server {
    	listen       8080;
    	server_name  localhost;
    	#charset koi8-r;
    
    	access_log C:/StandAlone/www/mystandaloneapp.com/log/access.log;
        error_log  C:/StandAlone/www/mystandaloneapp.com/log/error.log;
        root       C:/StandAlone/www/mystandaloneapp.com;
        index      index.html;
    
    	location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header  Host $http_host;
            proxy_redirect    off;
            try_files C:/StandAlone/www/maintenance.html $uri $uri/index.html $uri.html @ruby;
        }
    
        location @ruby {
            proxy_pass http://mystandaloneapp;
        }
    }
    
  23. That’s it. now you should be able to run, thin start from within the rails app, and then double click nginx.exe from within the nginx directory, and see the default rails website running at http://localhost:8080.

5 Comments

Leave a comment
  1. Luis Lavena 2011/03/05 at 3:01 pm #

    Hello,

    Step 12 and 13 should be only one: gem install sqlite3-ruby

    Unless you’re using latest version of Rails 3, ActiveRecord will complain about the lack of “sqlite3-ruby”

    Also, in relation to the platform, –platform=ruby triggers to build gems from native code, which means you need headers and link libraries for sqlite3 to successfully compile.

    Since the gem author already provided binaries, is safe to avoid.

    –platform=ruby should be used in case of certain gems that their binaries do not work for the version of Ruby you’re using. One example was the pg gem or the latest JSON gem, which misses binaries for Ruby 1.8.7

    Hope this clears up a bit the “details” on what –platform during gem installation means.

    Cheers.

  2. Andrés Botero 2011/03/22 at 2:00 am #

    Hello there!

    Wow, this looks excellent! I’ve been running nginx and PHP-FPM on Windows for a while (mostly self-taught developing), and it’s nice to see a Ruby implementation.

    I’m going to try it out and comment back as soon as I have a working application.

    Keep it up!

  3. beinghuman 2011/03/31 at 10:18 am #

    Thanks a lot ;) .

  4. klehner 2011/04/06 at 7:00 am #

    Is it possible to have thin and nginx start as a service on Windows? The goal is to not have the customer need to do anything to get the application going.

  5. Deacon 2011/04/06 at 7:48 pm #

    Hi there.
    Noob alert.

    What if I got already a project, how do I proceed? What should I change?

    Thanks