I had a fairly complex Ruby on Rails application that I wanted to deploy on my server, and with a very specific requirement. I needed to create a number of subdomains, and each of those subdomains would run the same application but with a different database and showing a different logo, so that I ended up with self-contained websites for each subdomain. I did not want to create a separate copy of the application code on the server for each domain, since that would be hard to maintain.

As it turns out, Ruby on Rails’s environments can be used to do the job. Each subdomain would cause the code to run in a different environment, and the environment would specify the name of the database to use. The biggest issue, though, was to find a way to let Apache’s virtual host somehow cause Rails to run the application instance using the environment specific by the virtual host. I used Apache’s passenger module to run my application.

As an example, let’s say that we have one application called abc of which we want to run two instances: inst1 and inst2 (with correspondingly named databases). We create two new enviroments (apart from the development, test and production enviroments that we already have, but we won’t use any of these on the server):

Environment 1:

Rails.application.configure do
  ...
end

Environment 2:

Rails.application.configure do
  ...
end

We don’t actually have to put anything special in these files – the configuration can be the same as the standard production environment’s configuration – but they need to exist in order to have two new environments.

Setting up a database for each environment

The important changes go into database.yml:

default:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: myuser
  password: mypass
  host: localhost

When run using environment inst1, the application will now use MySQL database inst1, while the same goes for inst2.

Letting Apache choose the environment

Rails must now have a way of selecting the correct environment for each request. Since it is the subdomain (e.g. inst1.example.com and inst2.example.com) that decides the environment, this setup will involve virtual hosts in Apache. Create a virtual host for each instance like this:

    ServerName inst1.example.com
    ServerAdmin alex@websofia.com
    DocumentRoot /usr/local/www/abc/public
    PassengerAppGroupName "inst1"
    RailsEnv inst1

    ServerName inst2.example.com
    ServerAdmin alex@websofia.com
    DocumentRoot /usr/local/www/abc/public
    PassengerAppGroupName "inst2"
    RailsEnv inst2

Also set permissions for the application directory (only once, not for each virtual host):

<Directory "/usr/local/www/abc/public">
  AllowOverride All
  Require all granted
  Options FollowSymLinks
  Allow from all
  Order allow,deny

And that’s it! Apache will now launch the Rails application through passenger with the correct environment for each request, depending on the subdomain used.