You are currently viewing Fun and Adventure with Ruby, Redmine, and Lighty

Fun and Adventure with Ruby, Redmine, and Lighty

For those who don’t know me all that well, I’m a lighttpd fan.  I use it for serving web data from all sorts of systems:  PHP, HHVM, Python, and even Lua have run on my servers, and all through lighttpd.  However, there’s always been one big outlier who just doesn’t get along with everything else, and that has been Ruby.

While lighttpd supports anything with fastcgi, for whatever reason, Ruby throws an absolute screaming fit when lighttpd tries to launch it, exiting with all sorts of errors related to the environment.  While trying to get Redmine running for Kerbal Space Program, due to time constraints, I ended up having to throw up my hands and use the recommended path of running ruby through nginx, and then proxying that through lighttpd.  Such an arrangement is far from ideal, as you effectively have two webservers running, both of which requiring maintenance and monitoring, and all sorts of hellish problems occur, such as trying to figure out what the user’s IP is.

So, imagine my dismay when, during my upgrade to Debian Jessie, I noticed that the backend nginx configuration managed to get completely blown away.  I figured that, since I’m currently not hosting any large sites or at work, I might as well pin this down.

Unfortunately, documentation pertaining to lighttpd and redmine are practically useless, ranging from completely outdated, to inapplicable.  Most of the surviving documentation, including on Redmine’s own site, suggest that you run nginx through lighttpd.  However, as mentioned before, this is not ideal.  I also wanted to figure this out in case I decided to get into Ruby development.

So, here’s the process I used to get everything up and running with Ruby 2.1.2, Lighttpd 1.4.35, and Redmine’s SVN trunk.  Keep in mind that your milage will vary, and you will likely need to mess around with things a bit to get them to work on your system.  My system is a sort of Frankenstein’s monster, and also has to support GitLab, which has very specific needs that I must balance with other systems.

Process

  1. I highly recommend not using RVM.  I had it installed on my system from the prior Redmine installation and it caused all sorts of hell with Bundler and friends.  To get rid of RVM, use rvm implode.  You may have to run it several times to completely get rid of it.  If you do choose to use RVM, you’re walking into uncharted territory.  Remember to update your ~/.bashrc and relog.
  2. Install the latest Ruby from source.  Debian works with it just fine, and it’s required for GitLab.  Remember to remove any other ruby installs on your system.
  3. Run gem install bundler as root.  Gem, for some reason, refuses to work as www-data, so the only way to get it working is to install everything into the system.
  4. In your Redmine installation directory, run echo gem "fcgi" > Gemfile.local.  You need fastcgi support in Redmine, so this’ll tell Bundler to grab that in addition to other gems during the install.
  5. Run bundler install --without development test rmagick.  rmagick  currently doesn’t compile on Debian Jessie due to a missing Magick-config command, and there are no packages available that provide it on x64.
  6. Edit your configuration to taste. This part shouldn’t go differently from the guide on Redmine’s site.
  7. cp public/dispatch.fcgi.example public/dispatch.fcgi – This is what will interface with lighttpd.  Thankfully, it doesn’t require any edits.

The Wrapper

Unfortunately, Ruby has problems when launched bare from lighttpd.  For whatever reason, some environmental variables get set incorrectly and – if you’ll pardon the pun – ruby goes off the rails.

/usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler/setup (LoadError)

So, the only way to get this running is to write a small wrapper script around the command that launches your FCGI dispatcher.  To do this, create a file called “launchRedmine.sh” in your Redmine installation directory, with the following contents:

#!/bin/bash

# Pipe stderr to stdout
exec 2>&1

# Set up our environmental variables.
export RAILS_ENV="production" # Either production or development.
export RAILS_RELATIVE_URL_ROOT="" # Blank if you're running from the root directory of your site.
export RAILS_ROOT="/host/bugs.nexisonline.net" # Duh.

# Change public to public or whatever your equivalent htdocs folder is, if needed.
ruby $RAILS_ROOT/htdocs/dispatch.fcgi

Remember to set it to executable and make it accessible to lighttpd. The rest of this is pretty simple.

The VHost Configuration

So, this is what my lighttpd.conf vhost configuration looks like.  Remember to change stuff as needed.

$HTTP["host"] == "bugs.nexisonline.net" {
    server.document-root = "/host/bugs.nexisonline.net/htdocs"
    server.indexfiles = ("dispatch.fcgi")
    server.error-handler-404 = "/dispatch.fcgi"
    url.rewrite-once = (
        "^/(.*\..+(?!html))$" => "$0",
        "^/(.*)\.(.*)" => "$0",
    )
    fastcgi.server = (
        ".fcgi" => (
            "redmine" => (
                "bin-path" => "/host/bugs.nexisonline.net/launchRedmine.sh",
                "socket" => "/var/run/redmine.sock", # Remember to create directories and set permissions for this as needed.
                "min-procs" => 1,
                "max-procs" => 4,
                "idle-timeout" => 120,
                "check-local" => "disable",
                "bin-environment" => (
                    "RAILS_ENV" => "production",
                    "RAILS_ROOT" => "/host/bugs.nexisonline.net",
                    "RUBY_HOME" => "/usr/lib/ruby/2.1.0",
                    "RAILS_RELATIVE_URL_ROOT" => ""
                ),
            ),
        ),
    )
}

I hope this helps someone out there in the same situation.