Archive for January, 2010

HOWTO Massive virtual hosting on tomcat

Thursday, January 7th, 2010

I found out today that tomcat virtual hosts are pretty lame. I thought that these all java based tomcat`s fancy plugins are much more powerful than old, simpleapache httpd. Well they aren`t. I wasn`t able to configure massive virtual hosting for servlets. I wanted to run diffrent web application based on domain name that comes in URL. For example myapp1.example.com would run application myapp1, myapp2.example.com would run myapp2, etc. And there could be hundreds of them so I didn`t want to add hundreds of entries in server.xml config file. I`m a lazy person ;-)

In order to configure virtual hosting based on above assumptions I used apache http server as a proxy to tomcat.
First you need to add wildcard records to your domain (example.com) so that records of all its subdomains can be resolved to IP address of your server. Following record should be added to your bind server zone config:

*   IN   A   1.2.3.4

where 1.2.3.4 is IP address of your server.

Next you need to configure httpd server. Please make sure that you have ajp proxy module installed on your server, as connections to tomcat are based on AJP protocol. On CentOS/RHEL 5 this module is included in standard httpd package (see /etc/httpd/conf.d/proxy_ajp.conf).
Now you need to create configuration for your virual hosts. I created a new file /etc/httpd/conf.d/tomcat-vhosting.conf:

UseCanonicalName Off
RewriteEngine On

# vhost map using perl script
RewriteMap vhost prg:/usr/local/bin/apache-getvhost.pl

# do no rewrite restricted names
RewriteCond %{SERVER_NAME} !^docs\.
RewriteCond %{SERVER_NAME} !^examples\.
RewriteCond %{SERVER_NAME} !^host-manager\.
RewriteCond %{SERVER_NAME} !^ROOT\.

# rewrite it
RewriteRule ^/(.*)$ ajp://localhost:8009/${vhost:%{SERVER_NAME}}/$1 [P]

Quite simple and cool, isn`t it? :-) I`m sure that you probably expected VirtualHost directives, but all you need is a powerfull rewriting feature of apache. This configuration allows to access myapp application located in tomcat`s webapps directory via http://myapp.example.com.
I used custom rewrite map which is a simple perl script. All it does is extract subdomain from server name based on URL.

Put the following in /usr/local/bin/apache-getvhost.pl

#!/usr/bin/perl

$| = 1;

while (<STDIN>) {
  if (/(.*?)\.example\.com/)      {
      print $1."\n";
  } else {
      print $_."\n";
  }
}

and make it executable

chmod +x /usr/local/bin/apache-getvhost.pl

Now all you need to do is provide some applications to tomcat.