Ravings on CS, OSs, PLs, SF, and other things geeky...

Getting a rails application to run on Apache is a real PITA to stay the least. First of there are four ways of doing it:

  • Apache with FastCGI
  • Apache with the new FastCGI, known as fcgid
  • Apache with mod_ruby, plain
  • Apache with mod_ruby, using the rail dispatcher (as of version 1.2.6)

None of these work particularly well, and even with all the tutorials out there it took quite some fiddling to get it right, and I gave upon getting mod_ruby to work.

To begin with the application I wanted to deploy was Radiant CMS. After having deployed it to the appropriate directory I set about getting apache to run it. I confirmed it worked with WebBrick and thought the rest should be easy.

I won’t go into how various ruby packages were installed as there are plenty of tutorials out there covering it, instead I will concentrate on the Apache set up. For the record this was done on a Gentoo Linux box, and some of the settings were replicated on a Debian Sarge box with similar results.

The first one I got working, since it was the simplest, was the FastCGI setup:

<IfDefine FASTCGI>
    <IfModule mod_fastcgi.c>
        Listen 80
        NameVirtualHost *:80
        #DefaultInitEnv RAILS_ENV production

        <VirtualHost *:80>
            DocumentRoot /var/www/localhost/radiant/public

            <Directory /var/www/localhost/radiant/public>
                Options ExecCGI +FollowSymLinks
                AllowOverride All
                order allow,deny
                allow from all
            </Directory>
        </VirtualHost>
    </IfModule>
</IfDefine>

Note that the DefaultInitEnv RAILS_ENV production directive is not supported by the module, requiring a change to the config/environment.rb to hard code the environment selection. Without which it would start up in development mode.

The problem with FastCGI is of course not that it is too slow, but more that it seems quirky and leaves the FastCGI server processes hanging some of which even hang after Apache shut-down. Thinking this was not acceptable I pressed on to get mod_fcgid working.

At first it ran okey except all the images and style sheets wouldn’t load, making things appear both ugly and slow. The fcgid module requires that you explicitly set the handler for it to process any files. First I did this on the directory, which made the handler deny any requests for anything but .fcgi files. This was easily fixed by moving the SetHandler directive to a more explicit File container thus:

<IfDefine FCGID>
    <IfModule mod_fcgid.c>
        #IdleTimeout 60
        #ProcessLifeTime 3600
        #MaxProcessCount 8
        #DefaultMaxClassProcessCount 60
        #DefaultMinClassProcessCount 3
        IPCConnectTimeout 10
        IPCCommTimeout 60

        AddHandler fcgid-script .fcgi

        Listen 80
        NameVirtualHost *:80
        DefaultInitEnv RAILS_ENV production

        <Files *.fcgi>
            SetHandler fcgid-script
            Options ExecCGI +FollowSymLinks
            allow from all
        </Files> 

        <VirtualHost *:80>
            DocumentRoot /var/www/localhost/radiant/public
            <Directory /var/www/localhost/radiant/public>
                Options +FollowSymLinks
                #SetHandler fcgid-script
                AllowOverride All
                order allow,deny
                allow from all
            </Directory>
        </VirtualHost>
    </IfModule>
</IfDefine>

Here the DefaultInitEnv RAILS_ENV production directive happily works, and this still seems like the optimum solution.

For the rest, there was mod_ruby, I never managed to get it running but just for the record the setup is below so if you can tell me what might be wrong please read on. All in all, it was a pain to setup and PHP still seems to run smoother. However when it comes to customizing my web site, Radiant offered an elegant structure which is highly customizable and easily maintainable. That coupled with my interest in Ruby and it all seems worth it.

First there is the plain version which uses Apache::RubyRun. After modifying the public/.htaccess file to use dipatch.rb instead of the cgi files I used the the following settings:

<IfDefine RUBY>
    #DefaultInitEnv RAILS_ENV production
    <IfModule mod_ruby.c>
        RubyRequire apache/ruby-run
        RubySafeLevel 0
        RubyRequire rubygems
        <Files *.rb>
            SetHandler ruby-object
            RubyHandler Apache::RubyRun.instance
        </Files>

        Listen 80
        NameVirtualHost *:80

        <VirtualHost *:80>
            DocumentRoot /var/www/localhost/radiant/public

            <Directory /var/www/localhost/radiant/public>
                Options ExecCGI +FollowSymLinks
                AllowOverride All
                order allow,deny
                allow from all
                RubyOption rails_env production
            </Directory>
        </VirtualHost>
    </IfModule>
</IfDefine>

The rails_env option didn’t seem to work either and DefaultInitEnv was not accepted. Also the RubyRequire rubybems seemed to be required so that rails classes would be properly located. Still I ended up with the following errors:

[error] mod_ruby: error in ruby
[error] mod_ruby: /usr/lib/ruby/gems/1.8/gems/radiant-0.6.2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:266:in `load_missing_constant': uninitialized constant ADDITIONAL_LOAD_PATHS (NameError)
[error] mod_ruby:   from /usr/lib/ruby/gems/1.8/gems/radiant-0.6.2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:452:in `const_missing'
[error] mod_ruby:   from /var/www/localhost/radiant/public/dispatch.rb:10
[error] mod_ruby:   from /usr/lib/ruby/1.8/apache/ruby-run.rb:53:in `handler'

In order to try out the rails dispatcher (mod_ruby version 1.2.6 and up) I modified my settings such:

<IfDefine RUBY> 
    #DefaultInitEnv RAILS_ENV production

    <IfModule mod_ruby.c>
        RubySafeLevel 0
        # If you use RubyGem
        RubyRequire rubygems
        RubyRequire apache/rails-dispatcher

        #RubyRequire apache/ruby-run
        <Files *.rb>
            SetHandler ruby-object
            RubyHandler Apache::RailsDispatcher.instance
            RubyTransHandler Apache::RailsDispatcher.instance
            RubyOption rails_uri_root /var/www/localhost/radiant/public
            RubyOption rails_root /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/
            RubyOption rails_env production
        </Files>

        Listen 80
        NameVirtualHost *:80

        <VirtualHost *:80>
            DocumentRoot /var/www/localhost/radiant/public

            <Directory /var/www/localhost/radiant/public>
                Options ExecCGI +FollowSymLinks
                SetHandler ruby-object
                AllowOverride All
                order allow,deny
                allow from all
            </Directory>
        </VirtualHost>
    </IfModule>
</IfDefine>

With this setup the .rb file isn’t even processed, and nothing I could find seemed to indicate it should be otherwise. Any further information on how to run with mod_ruby would be greatly appreciated.