Run Rails 2 Application on Shared Hosting
By Jimmy Bonney | December 7, 2013
Redmine is a project management web application. It comes with plenty of features and this would deserve a post in itself to go through them all but this is another story. We have been using Redmine mainly to track issues and submit new ideas for our applications. Currently, it is in use for D-Sight Desktop and its different plugins and it allows us to make sure that each release get its fair share of bug fix (when needed) and new features.
The beauty of Redmine is that it can be easily self-hosted which really makes it a tool of choice (understand feature-full for a really low price) when getting the company off the ground. In our case, problems started a couple of months ago after our hosting provider decided to go through a server migration which resulted in our Redmine application not being able to run any more.
Following the server migration, plenty of issues started popping up and priorities being what they are, Redmine availability got postponed. Well, as everything else, at some point, this needed to get fixed and this post will detail what needed to be done to restore access.
Run Application Through CPanel
Starting the application through CPanel simply failed. Any attempt would provide the traditional message that the application was started but going back to the list of applications would just displayed a status “Stopped” in front of the application.
Ruby Gems Update
It seems that the gems that were originally installed on the server were not available any more. An update was probably performed during the migration resulting in gems being simply replaced.
The shared hosting provider allow to install some gem for the local user. So a rake gem:install
can take care of installing missing gems locally but this requires that the application also look into the current user gem folder.
Bash Profile
Ensure that the GEM_PATH
is correctly defined and contained the current user local gems folder. Edit your ~/.bash_profile
and ensure that the following is in place (in our case, there was some error in the GEM_PATH
variable that needed to be fixed).
1
2
3
4
5
6
7
export RAILS_ENV="production"
export GEM_HOME="/home/username/.gem/ruby/1.8"
export GEM_PATH="/home/username/.gem/ruby/1.8/gems:/home/username/.gem/ruby/1.8:/home/username/ruby/gems/1.8:/usr/lib/ruby/gems/1.8"
export GEM_CACHE=$GEM_HOME/cache
export PATH=$PATH:$GEM_HOME/bin
[[ -s "$HOME/.r
vm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
Redmine Environment
For the remaining of the article, consider that the application is installed under ~/rails_apps/redmine/
.
Have a look in your Rails application at the config/environment.rb
file. Some of the variables that need to be looked into are the following:
1
2
3
ENV['RAILS_ENV'] ||= 'production' # If no RAILS_ENV is specified, run in production
# ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine' # We had to comment this (see below)
RAILS_GEM_VERSION = '2.3.18' unless defined? RAILS_GEM_VERSION
In our case, I had to comment the line ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine'
so that it doesn’t consider that the application is in the redmine
subfolder. It used to work properly before with this setting but I think that the changes made in the .htaccess
file (see below) cause some problems when trying to access the static resources (images, CSS, JavaScript, etc…).
Ensure that the RAILS_GEM_VERSION
specified is available among the gems that are installed. To do so, one can run the following command:
1
gem list --local | grep rails
The output will be something similar to the following:
1
2
3
4
5
coffee-rails (3.2.2)
jquery-rails (2.0.2)
odbc-rails (1.5)
rails (2.3.18, 2.3.15, 2.3.14, 2.3.11)
sass-rails (3.2.5)
Run the Application
From the application folder (~/rails_apps/redmine/
), see if the application starts. This is simply done by executing mongrel_rails start -p 12001
. If our case, it didn’t start at this stage and we were welcome by the following error message:
1
Error calling Dispatcher.dispatch #<NoMethodError: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.split>
“Fortunately”, this error has been around for a while and a fix is available. Create a file config/initializers/mongrel.rb
and paste the content found in this gist. The content might need to be adapted to reflect the Rails version that you are using. Below is the modification to include multiple version of Rails.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
if ['2.3.8', '2.3.9', '2.3.10', '2.3.11', '2.3.14', '2.3.15', '2.3.16', '2.3.18'].include?(Rails.version) && Gem.available?('mongrel', Gem::Requirement.new('~>1.1.5')) && self.class.const_defined?(:Mongrel)
# Pulled right from latest rack. Old looked like this in 1.1.0 version.
#
# def [](k)
# super(@names[k] ||= @names[k.downcase])
# end
#
module Rack
module Utils
class HeaderHash < Hash
def [](k)
super(@names[k]) if @names[k]
super(@names[k.downcase])
end
end
end
end
# Code pulled from the ticket above.
#
class Mongrel::CGIWrapper
def header_with_rails_fix(options = 'text/html')
@head['cookie'] = options.delete('cookie').flatten.map { |v| v.sub(/^\n/,'') } if options.class != String and options['cookie']
header_without_rails_fix(options)
end
alias_method_chain :header, :rails_fix
end
# Pulled right from 2.3.8 ActionPack. Simple diff was
#
# if headers.include?('Set-Cookie')
# headers['cookie'] = headers.delete('Set-Cookie').split("\n")
# end
#
# to
#
# if headers['Set-Cookie']
# headers['cookie'] = headers.delete('Set-Cookie').split("\n")
# end
#
module ActionController
class CGIHandler
def self.dispatch_cgi(app, cgi, out = $stdout)
env = cgi.__send__(:env_table)
env.delete "HTTP_CONTENT_LENGTH"
cgi.stdinput.extend ProperStream
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
env.update({
"rack.version" => [0,1],
"rack.input" => cgi.stdinput,
"rack.errors" => $stderr,
"rack.multithread" => false,
"rack.multiprocess" => true,
"rack.run_once" => false,
"rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
})
env["QUERY_STRING"] ||= ""
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
env["REQUEST_PATH"] ||= "/"
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
status, headers, body = app.call(env)
begin
out.binmode if out.respond_to?(:binmode)
out.sync = false if out.respond_to?(:sync=)
headers['Status'] = status.to_s
if headers['Set-Cookie']
headers['cookie'] = headers.delete('Set-Cookie').split("\n")
end
out.write(cgi.header(headers))
body.each { |part|
out.write part
out.flush if out.respond_to?(:flush)
}
ensure
body.close if body.respond_to?(:close)
end
end
end
end
end
Once this is in place, the application should start properly. It can then be daemonized in order to run it in the background.
1
mongrel_rails start -p 12001 -d
Access the application
If the application runs, we are halfway there. It needs of course to be accessible from the outside so check that you can access http://example.com:12001 from your browser. In our case, no luck here.
From the server itself, check that the application is accessible. This is done by running a curl 127.0.0.1:12001
from the console. This should probably work at this stage and if you are restoring access to Redmine, then you should see something like:
1
<html><body>You are being <a href="http://127.0.0.1:12001/login?back_url=http%3A%2F%2F127.0.0.1%3A12005%2F">redirected</a>.</body></html>
HTAccess
Then, access from the outside is a matter of setting properly Apache rewrite rules. In our case, we had to identify the HTAccess rules that were previously in place for the application and update them.
All rules related to the Redmine application that were in ~/www/.htaccess
have been commented out. We have created a .htaccess
file inside the application folder itself (i.e. in ~/rails_apps/redmine/.htaccess
) and filled it with the following:
1
2
3
4
RewriteEngine on
RewriteCond %{HTTP_HOST} ^redmine.example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.redmine.example.com$
RewriteRule ^(.*)$ "http://127.0.0.1:12001%{REQUEST_URI}" [P,L]
As a result, Redmine is now accessible directly from http://redmine.example.com. Since this is on a subdomain of the application, this is the reason why # ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine'
needed to be commented in config/environment.rb
.
Some additional resources
I haven’t completely tried out the following solutions but they may offer a leaner and clearer approach to what we have done here:
Sources
Credits Image
Related Articles
It seems that other articles are somewhat related to this one. Similar articles are identified through a set of keywords so this might not be 100% accurate, but I hope this can interest you.
Link Object and Subject with ACL9 without Database View
Published on May 5, 2013
Drupal Private Download Folder
Published on August 26, 2009
Fix Drupal Website Not Loading
Published on December 2, 2013
Somewhat related articles
Link Object and Subject with ACL9 without Database View
Published on May 5, 2013
Drupal Private Download Folder
Published on August 26, 2009
Fix Drupal Website Not Loading
Published on December 2, 2013
For the time being, comments are managed by Disqus, a third-party library. I will eventually replace it with another solution, but the timeline is unclear. Considering the amount of data being loaded, if you would like to view comments or post a comment, click on the button below. For more information about why you see this button, take a look at the following article.