Ubuntu Feisty - Apache vhosts, rails and mongrels

There are several ways of serving a Ruby on Rails application, one of which is to use Apache to proxy requests to mongrels.

There are a few ways of completing this and we're going to look at one simple solution. Other ways will be looked at in future articles.


Setup

Just a quick note on where we are in the setup. I have my base Ubuntu Feisty installed which I updated and secured. I then installed MySQL and Ruby on Rails as per this article.

Once the basics were done I then proceed to install Apache and PHP. Of course, you can leave out the PHP part.

I then created a public_html folder in my home partition and created the correct permissions as shown here.

Rails Application

You can use a pre-existing Rails application or, like me, create a new one from scratch. To create a new one, move into your public_html folder:

cd /home/demo/public_html

and create a new Ruby on Rails application:

rails railsapp

move into the directory:

cd railsapp

You will notice that the created folders are very similar to the default vhosts layout I describe here

As such, we don't need to create any extra folders as the Apache logs can go into /log and so on.

Mongrels

Let's install the mongrels via ruby gems:

sudo gem install mongrel --include-dependencies

Once done we can move onto the Apache configuration.

Apache modules

Apache will need certain modules to be enabled to allow it to pass the requests to the mongrels.

There are four specific modules that we need. Enable them like so:

sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod rewrite

As suggested by the module commands, reload Apache:

sudo /etc/init.d/apache2 force-reload

Virtual host

Now we need to create a new virtual host for the 'railsapp' we created earlier:

sudo nano /etc/apache2/sites-available/domain.com

Obviously use your domain name instead of my example of domain.com

At this stage we are only doing a basic configuration so you can enter the following in the vhosts file:

<VirtualHost *:80>
  ServerName domain.com
  ServerAlias www.domain.com

  DocumentRoot /home/demo/public_html/railsapp/public

  RewriteEngine On

  <Proxy balancer://mongrelcluster>
    BalancerMember http://127.0.0.1:8000
    BalancerMember http://127.0.0.1:8001
  </Proxy>

  # Redirect all non-static requests to Mongrel
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://mongrelcluster%{REQUEST_URI} [P,QSA,L]

  ProxyPass / balancer://mongrelcluster/
  ProxyPassReverse / balancer://mongrelcluster/
  ProxyPreserveHost on

  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  # Custom log file locations
  ErrorLog  /home/demo/public_html/railsapp/log/error.log
  CustomLog /home/demo/public_html/railsapp/log/access.log combined

</VirtualHost>

Take each section at a time and you will see that the basics are exactly the same as for a 'normal' vhost configuration.

We have the ServerName, DocumentRoot and Log locations.

Where it differs is the addition of the Proxy settings.

In this example, we will use 2 mongrels running on ports 8000 and 8001 in a balancer named 'mongrelcluster' (call it something more expressive if you have several rails sites - it is also not technically a mongrel cluster but, hey, it's a good name).

The next sections tell Apache to pass the proxy request to the defined balancer. It then sets the permissions on the Proxy so we don't have a dreaded permissions error.

Do note the trailing slash (/) is very important in the ProxyPass settings. Miss them out and it won't work.

Enable

After all of this, don't forget to enable the new vhost:

sudo a2ensite domain.com

And as requested:

sudo /etc/init.d/apache2 reload

If you have a warning regarding mixed ports, you will need to ensure the default vhost has been changed to reflect specific port access as follows:

NameVirtualHost *:80
<VirtualHost *:80>
...
...

Reload Apache and the warning will have gone.

Start your engines

All that's left is to start the two mongrel processes on the ports defined in the vhost. If you are not already in your railsapp directory, move there now:

cd /home/demo/public_html/railsapp

We will start two separate mongrels:

mongrel_rails start -d -e production -p 8000 -P log/mongrel8000.pid
mongrel_rails start -d -e production -p 8001 -P log/mongrel8001.pid

As Feisty uses ruby -v1.8.5 as the default you will received a warning:

** Ruby version is not up-to-date; loading cgi_multipart_eof_fix

It is just a warning and, until the aptitude version is updated or you install from source, nothing to be concerned about.

Navigate

Once done, navigate to your domain:

http://www.domain.com

And, if you created a new Ruby on Rails application, you will see this:

Ruby on Rails Welcome Page

Summary

The next article will concentrate on mongrel clusters and ensuring your mongrels survive a reboot.

PickledOnion.

Article Comments:

sean commented Wed Oct 17 06:28:55 UTC 2007:

Great article! I just have one question: I ran through this and everything went according to plan. The only problem I have is that when I type the name of my domain (www.domain.com in your example; I used www.test.com), my browser goes to the internet to get it and obviously I don't own www.test.com, so the real test.com comes up. My site is running on an internal (inside my company) server located at a 192.168.xxx.xxx address. What adjustments would I have to make in order to set up a mongrel cluster with Apache on an internal site at such an address?

Thanks for your effort and your great site.

Sean

PickledOnion commented Wed Oct 17 09:30:32 UTC 2007:

Hi Sean,

You are meant to replace my example of 'domain.com' with your own domain so your Slice can then serve the domain. Ensure you have your DNS configured to point to your Slice.

I am not able to help with issues not related to Slices I'm afraid. However, you will need to adjust the /etc/hosts file so test.com points to your IP.

PickledOnion.

Daniel Lucraft commented Wed Nov 07 08:58:42 UTC 2007:

If you are getting 404 not found errors after this on other virtual hosts you have defined, try setting their ports to "*:80" as well. That fixed it for me.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)