Ubuntu Gutsy - 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 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

As I am using rubygems 0.9.5 it installed the dependencies automatically and, on my setup, installed the following:

gem_plugin-0.2.3
cgi_multipart_eof_fix-2.5.0
daemons-1.0.9
fastthread-1.0.1
mongrel-1.1.1

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 get a warning regarding mixed ports, you need to sort out the NameVirtualHost settings as described in the Apache Virtual Hosts articles.

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

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:

Jay commented Thu Nov 29 15:26:28 UTC 2007:

In regards to these lines of the vhost file: # Redirect all non-static requests to Mongrel RewriteCond %{DOCUMENTROOT}/%{REQUESTFILENAME} !-f RewriteRule ^/(.*)$ balancer://mongrelcluster%{REQUEST_URI} [P,QSA,L]

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

I found that all my traffic was actually being routed to the cluster via that ProxyPass / directive. The rewrite rule was not actually doing anything. I simply commented out the first ProxyPass line, and everything seems to work as expected now.

Any thoughts?

PickledOnion commented Thu Nov 29 16:06:20 UTC 2007:

Hi Jay,

Sorry I am not sure what you are saying.

What wasn't working? The rewrite rule or the ProxyPass lines?

All your traffic meaning all your vhosts? Or the traffic for one vhost only (meaning the static traffic)?

PickledOnion.

Damien commented Sat Dec 01 01:29:48 UTC 2007:

Do you need to go back and modify the permissions after creating the rails project? After following the guide and firing up my test app, I get a 403 error saying that I don't have access to / on the server..

Damien commented Sat Dec 01 10:15:14 UTC 2007:

I found the problem - I'd renamed the mongrel cluster but forgotten to amend the RewriteRule line to reflect it. Stupid me..

Jay commented Sat Dec 01 19:57:38 UTC 2007:

Hi,

Sorry my post got a little messed up. I am serving my static files out of a completely different directory than my rails application. (e.g. rails app is in /home/jay/rails/myapp and the sites's DocumentRoot is /home/jay/publichtml/site/public). Say there's an image: /home/jay/publichtml/site/public/images/test.gif. I found that if I had the ProxyPass / balancer://mongrelcluster/ line, my server tried to serve me /home/jay/rails/myapp/public/images/test.gif instead of /home/jay/public_html/site/public/images/test.gif. The rewrite conditions were being overridden by that ProxyPass line. ALL TRAFFIC, not just not-found static files were getting driven to the balancer.

If I comment out the ProxyPass / balancer://mongrelcluster/ line, things behave as expected. Static files that are found in /home/jay/public_html/site/public/ are served, otherwise it gets redirected to the cluster.

Hope this is clear.

PickledOnion commented Sat Dec 01 21:01:58 UTC 2007:

Jay,

Thanks for clarifying the post.

I wonder if the different base directory makes a difference? I can't think it would be anything else.

I must admit, the vhosts file is very simple and you may have to tweak it for different layouts (exactly as you have).

How did you come by the solution? Trial and error, or did you see a flaw in the vhost example I've got here?

Anyway, thanks again.

PickledOnion.

Jay commented Sun Dec 02 01:31:14 UTC 2007:

I would guess it's the different base directory, but I would have to study how apache looks at the vhost file to confirm. I would suspect that it would follow directives from the top-down, but, judging by my experience, the ProxyPass directive certainly trumped the RewriteCond/RewriteRule pair just before it.

I came about the solution by trial and error after following your guide. I'm curious though, as to why that ProxyPass / line is included in your guide. It seems unnecessary. I guess it helped that I used to run my app through FastCGI, and the .htaccess required to run dispatch.fcgi on a 404 is almost identical (and works without any proxypass settings).

Liam commented Sat Jan 12 04:30:05 UTC 2008:

Have followed everything and all is working...However - somewhere along the line I have messed up or am not understanding too well - www.mydomain.com correctly goes to railsapp - and default page is Ruby Welcome Aboard -

mydomain.com (no www) still goes to Apache2-default

what file do I have to edit to have mydomain.com go to railsapp also? Apologioes in advance if it is obvious!

PickledOnion commented Mon Jan 14 12:46:45 UTC 2008:

Liam,

It sounds as if there is a typo or error on the vhosts file where the domains are defined.

It is also possible that the dns record for the main domain is not configured correctly?

I would check both carefully and see if that is the case.

PickledOnion

RedWillow commented Tue Jan 15 18:24:14 UTC 2008:

One minor thing that got me hosed up. I've been following all of the tutorials religiously, but I copied a vhost file from a previous tutorial, and then just added the proxying statements from this file. Where it hosed me was that the other examples have a directory called "logs", but railsapp creates the directory called "log". Since I had the path to the logs directory from the other examples, apache2 choked on it. Figured I'd point it out just in case other noobs ran into a similar issue.

David commented Thu Jan 17 17:38:28 UTC 2008:

I used these vhost directives, but I got a connection refused refused error when trying to forward to 127.0.0.1. I followed the security tutorial earlier for Gutsy, and I noticed that my iptables setting is denying connections to 127.0.0.1. To get around this, I forwarded the proxy to my public IP address, and it worked fine. Do you think this is acceptable or should I allow access to 127.0.0.1? If so, how can I allow access to 127.0.0.1 from localhost.

David commented Thu Jan 17 19:11:15 UTC 2008:

Also, any thoughts on how I would redirect all traffic to mydomain.com to www.mydomain.com with this proxy setup?

Frank Cort commented Sun Feb 10 05:38:53 UTC 2008:

Liam, I too had the same problem you did.

To fix it, I removed the ServerName entry at the bottom /etc/apache2/apache2.conf file and then restarted apache2.

I now get the "Could not reliably determine the server's fully qualified domain name,..." but it seems to work.

Calvin commented Wed Mar 05 03:35:32 UTC 2008:

Hello,

I have followed the guide from start to setup my RoR server. Everything has been really smooth, except I ran into a problem when I was trying to set up mongrel. I got an error message stating 'Failed to build gem native extension.' Not sure if anyone has ran into the same problem.

Anyhow, I was able to fix this error once I installed build-essential. So just do a sudo apt-get install build-essential, and install mongrel again. It should work then.

lambo commented Fri Mar 28 00:48:06 UTC 2008:

So after following the tutorials all the way to the end of this one, I got everything working with 2 mongrels and apache as the front end. I then bring up my homepage, and I successfully get the index.html file that rails serves from its public directory. When I click the link "About your applications environment", everything breaks. When I holding the mouse over the link, it is trying to link to "http://www.mydomain.com/rails/info/properties". So if I wanted to get this working, where would I point this link too? Obviously within the public/index.html file, there is the link that points to /rails/info/properties. What would this be changed to, to get the environment properties to be discovered here? I know this is a little trivial, but it would be nice to know what the change would be. I would assume the change would be the same for nginx too?

marc commented Mon Mar 31 08:04:52 UTC 2008:

I am having the same problem as lambo. It points to the index.html file in the public folder, but the "About your applications environment" link doesn't work. When I rename the index.html file, I get a rails error saying "The page you were looking for doesn't exist."

paul k commented Tue Apr 01 04:43:24 UTC 2008:

lambo mark and I share the same problem. The problem persists when looking for any other part of my rails application, such as a view. I'm so confused ),:

t3i commented Sun Apr 27 16:49:22 UTC 2008:

Liam and Frank Cort,

I also had the www-less url going to the "it works" page. After removing the ServerName line, as per franks suggestion, i then changed it to 'ServerName localhost', which seems to work and not throw an error. I'm still wondering why...

Carlos commented Mon Apr 28 15:25:26 UTC 2008:

I am getting the same problem as well. The default Ror page appears but not any other page from my Rails App. Wondering if anyone else has figured out this problem.

Jam commented Mon May 12 02:03:36 UTC 2008:

I'm also getting the "The page you were looking for doesn't exist." on the Rails Welcome page. I followed the instructions to Ubuntu Hardy though. I'm fairly confident I did it right. Also, when I navigate to mydomain.com/Testcontroller, I get the 500 error "We're sorry, but something went wrong" Does anyone know why this is???

PickledOnion commented Mon May 12 09:30:16 UTC 2008:

Hi,

The reason for the 500 error will be shown in the error logs.

With Rails there are 3 main environments (you can crate others if you wish).

In production mode, the details of the environment are not available.

It is a basic security procedure with rails - I have gone through the article again and all works fine with it.

Cheers,

PickledOnion

mark commented Wed Jul 09 21:44:26 UTC 2008:

Had a similar problem to Calvin with: "error message stating 'Failed to build gem native extension.'", the solution he posted didn't work for me but this did: sudo apt-get install ruby1.8-dev ...then install mongrel as stated

Tarun Kumar commented Fri Jan 16 02:25:54 UTC 2009:

Hi, Guide is excellent. it's working like a hot knife in the butter. I successuflly setup my ubuntu box with mongrel + apache. Calvine & mark you should install mongrel using "gem install mongrel mongrelcluster". it will work. Thanks for this informative post.

nuks commented Thu Oct 08 10:06:39 UTC 2009:

Two words. Great article!

rickster commented Wed Jun 12 19:47:28 UTC 2013:

for those reading this that are running into the error with the main welcome RoR page showing up, but none of the links or subsequent pages working......the fix that worked for me was to add 'RailsEnv development' to the Apache virtual host file. hope that helps someone :)

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)