In addition to the ‘development Ruby on Rails’ environment and Appliance VPS product, we’ve recently worked through the software requirements and dependencies of a ‘production’ Ruby on Rails hosting environment and VPS.
The following technical information outlines the broad sysadmin actions required to bring a ‘development’ Ruby on Rails application online within an Apache webserver & seperate VPS/system for hosting the application to the Internet in a ‘production’ setting (as opposed to running the application within “rails server” for testing).
Some assumptions that ‘complicate’ this deployment (complications which are dealt with in the actions outlined below) are that the development Ruby on Rails environment is Ruby 1.9.x and Rails 3.0.9.
This effectively means that most of the easily installable Operating System packages for (say) Debian or Ubuntu Linux aren’t going to work out, in that most Linux-based operating systems install Ruby 1.8.x and an older version of Rails & RubyGems, along with an older version of the Apache module that’s commonly used to present Ruby software to the web, being the “Passenger” module. Finally, we’ll assume in the following that you’re hosting the web application on a 64 bit Debian 6 (“Squeeze” by name) VPS.
So to “productionise” a Ruby 1.9.x and Rails 3.0.9 developed web application means that much software must be installed from source code or from the distributions made available from the software’s site itself, rather than just Operating System packages.
Based on the above requirements and assumptions, here’s the process for getting the relevant software onto a ‘vanilla’ Debian 6 system, with all commands run as the ‘root’ Linux user:
a) With a ‘minimal’ Debian 6 64 bit (x86_64) system, install the following Debian Packages after upgrading the Debian 6 system to the latest version of ‘base’ packages ie: an apt-get upgrade
apt-get install ruby1.9.1 libruby1.9.1
apt-get install build-essential
apt-get install apache2-prefork-dev
apt-get install libapr1-dev
apt-get install libaprutil1-dev apache2
apt-get install libxslt-dev libxml2-dev
apt-get install curl libcurl4-openssl-dev
Then either (or both) of the following depending on what DB environment is required by the Ruby on Rails application:
apt-get install libsqlite3-dev sqlite3
apt-get install mysql-server libmysqlclient16 libmysqlclient-dev mysql-client mysql-common
If you’re installing the mysql-server package, it will ask you to specify the mySQL ‘root’ user’s password.
The above yields ‘ruby’ as the binary/executable ‘/usr/bin/ruby1.9.1’, so to have the command line ‘ruby’ command, you can create a Linux ‘symlink’ of /usr/bin/ruby1.9.1 to /usr/bin/ruby
ie:
ln -s /usr/bin/ruby1.9.1 /usr/bin/ruby
b) Download & install RubyGems from http://rubyforge.org/projects/rubygems/ to the system, extract that file, cd into that extracted directory & run ‘ruby setup.rb
‘
cd /usr/local/src/
wget http://rubyforge.org/frs/download.php/75309/rubygems-1.8.10.tgz
tar xzf rubygems-1.8.10.tgz
cd rubygems-1.8.10
ruby setup.rb
Then, as above, if you want the ‘gem’ command-line executable, then do:
ln -s /usr/bin/gem1.9.1 /usr/bin/gem
c) Use Gem to install the following Gems:
(If you don’t need mysql, then you may not need to install it)
gem install mysql
gem install fastthread
That gives you a software base to bring your Ruby on Rails application development directory over from your development environment to this system and copy that development directory tree to the directory where you’d like it served from on this production server. eg: /var/www/app/
Once you’ve done so & we’ll assume that it’s been copied to the directory /var/www/app, you then should ensure that your app has a running environment compatible with this production environment, rather than the development environment, which in the case of the dev. environment we refer to in our previous post (being Ruby 1.9.x, RSpec, Rails 3.0.9, etc) means that all RSpec Tests should pass. Again, as per the development RoR environment outlined, this is accomplished with the following actions:
a) Remove the ‘rake’ directory from the development environment and check your ‘Gemfile’ to be sure that it lists any specific Gem version numbers that you may want.
cd /var/www/app/
rm -rf rake
vi Gemfile
b) Then run the bundle install
command to install the Ruby on Rails environment compatible with this production system and also (crucially) all the Gems that your application needs, and that may take some time as it downloads & installs the relevant Gems listed in your Gemfile.
Of course, if your Gemfile is small or non-existant, you can iterate with ‘gem install
gem install rake
gem install rails --version=3.0.9
gem install sqlite3
…
c) If you’re using RSpec (which we recommend), then all tests should run now without error:
cd /var/www/app
bundle exec rspec spec/
This gets your application working on the production system’s software environment, so now’s the time to get everything installed for Apache to be able to serve your Ruby on Rails application’s content.
As above, we’ve already installed Apache2 and its Development environment, so we now need to install the Passenger Gem and compile the Passenger Apache2 module itself. This is done with the following:
gem install passenger
Which among its actions, installs the following executable command:
/usr/bin/passenger-install-apache2-module
Running “passenger-install-apache2-module” steps through the process of validating your software environment (that it’s able to build the Passenger module etc & the common pre-req’ software needed is installed initially above from Debian/Ubuntu Linux Packages) and goes through the process of downloading the latest/relevant Passenger Module’s code and building and installing it.
The final output of ‘passenger-install-apache2-module’ looks something like:
——————————————–
The Apache 2 module was successfully installed.Please edit your Apache configuration file, and add these lines:
LoadModule passenger_module /usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.9/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.9
PassengerRuby /usr/bin/ruby1.9.1After you restart Apache, you are ready to deploy any number of Ruby on Rails
applications on Apache, without any further Ruby on Rails-specific
configuration!Deploying a Ruby on Rails application: an example
Suppose you have a Rails application in /somewhere. Add a virtual host to your
Apache configuration file and set its DocumentRoot to /somewhere/public:
ServerName www.yourhost.com
DocumentRoot /somewhere/public # <-- be sure to point to 'public'!
AllowOverride all # <-- relax Apache security settings Options -MultiViews # <-- MultiViews must be turned off
And that’s it! You may also want to check the Users Guide for security and
optimization tips, troubleshooting and other useful information:/usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.9/doc/Users guide Apache.html
——————————————–
These broad/general instructions require the following actions in a Debian Apache2 context:
a) Put the string “LoadModule passenger_module /usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.9/ext/apache2/mod_passenger.so” into the file /etc/apache2/mods-available/passenger.load
b) Put the following lines into /etc/apache2/mods-available/passenger.conf
file
PassengerRoot /usr/lib/ruby/gems/1.9.1/gems/passenger-3.0.9
PassengerRuby /usr/bin/ruby1.9.1
# see all passenger module directives here: http://www.modrails.com/documentation/Users%20guide.html
PassengerDefaultUser www-data
*Note: Updated to correctly set the user that the Rails App runs as by Apache using “PassengerDefaultUser” directive, otherwise the Rails App runs as user ‘nobody’, not the user that the Apache is running as!
c) Run (as root) to enable the configuration & settings for the Apache2 Passenger Module in the Debian/Ubuntu context:
a2enmod passenger
Now you’re ready to just configure Apache to serve that directory (/var/www/app in our example here) and there’s many ways to do that, but we’ll just outline using the defaults of Debian’s Apache2 package’s installed files here.
a) Load the following to the top of: /etc/apache2/sites-available/default
ServerAdmin webmaster@YOURDOMAIN
##DocumentRoot /var/www
DocumentRoot /var/www/app/public
# <-- be sure to point to 'public'!
AllowOverride all
# <-- relax Apache security settings
Options -MultiViews
# <-- MultiViews must be turned off
b) Restart Apache with that config:
/etc/init.d/apache2 restart
c) Check for any Apache startup errors in /var/log/apache2/error.log
of which there should just be the usual Apache startup line mentioning the use of the Passenger module, like:
[notice] Apache/2.2.16 (Debian) Phusion_Passenger/3.0.9 configured -- resuming normal operations
Now, if you use a SQL Lite DB in your application during development, then you should move the sqlite3 DB to a ‘production’ mode, which is done either “by the book” with the command:
cd /var/www/app
rake db:create RAILS_ENV=production
Which will create an empty ‘production’ DB.
Or, you could just rename your ‘development’ DB file to the ‘production’ filename with:
cd /var/www/app
cp db/development.sqlite3 db/production.sqlite3
This will preserve any DB contents from development into the production DB (which may or may not be what you want).
If you use mySQL or such for your DB requirements, then now’s the time to ensure that your DB is available to your application on the production system (eg: use mysqldump or such to transfer the relevant DB over to the mysql server running on this production host).
If you don’t do this, you may get the good ‘ole RoR Passenger error page of “Something went wrong” and if so, there may be nothing listed in the Apache error.log file, but you’ll see updated files in your app’s log/ directory, so check /var/www/app/log/production.log
That’s about it, this process has reliably put a number of customer Ruby 1.9.x on Rails 3.0.9 externally developed web applications online to the Internet via Apache webservers on Debian 6 Linux.
As always, feel free to contact us as a customer if you have any queries.
Updated to correctly set the user that the Rails App runs as by Apache using “PassengerDefaultUser” directive, otherwise the Rails App runs as user ‘nobody’, not the user that the Apache is running as.