This guide will cover getting Tomcat 5.5 running on a Debian testing machine and then getting it to play nicely with Apache 2. There are numerous problems with packaging Tomcat on Debian so it is stuck at version 4 which is fine for older applications but starting to be a pain if you write anything new. Fortunatly it isn't that hard to maintain your own Tomcat installation but you do need to setup a couple of scripts to make sure Tomcat is started correctly at boot.
Setting up Tomcat 5.5
If you have been using Tomcat 4.x for a long while then you are going to have a little bit to learn as some of the configuration files have changed. Probably the biggest change is the removal of the Logger element and creation of a unified connector. However, for the most part, you can just copy your config files over and make minor tweaks.
Download the latest tomcat package and unpack it in /usr/local/ then create a symlink to it so that it can be referred to as /usr/local/tomcat. This isn't essential and if you intend to run multiple servers may be more confusing than useful.
Setting up JK to Connect to Apache 2
This is a bit of a black art but I will try and make it as simple as possible. This would be a fairly simple process if the mod_jk module was already compiled and packaged for Apache 2 but the standard Debian repositories only contain a version compiled for Apache 1.3. There is a version of mod_jk2 compiled for Apache 2 but since JK2 is a very difficult to configure and only being maintained (rather than actively developed) it is probably a good idea to go with JK.
Step 1 - Get mod_jk
You can try and get a binary distribution but when I looked there wasn't a Debian specific build which means that you will have to build the connector from source (the files are under the Tomcat project).
I chose to grab the source for the 1.2.6 version since the Tomcat site currently lists 1.2.6 as the most stable version. You can get the sources from here you might also be able to get a pre-compiled binary from here. Unpack the source and move onto step 2.
Update: I have since upgraded to the 1.2.13 version but the instructions are the same. Note that there has been a tiny change in the naming strategy of the source tar ball name. The jk has been dropped from the file.
Step 2 - Compile mod_jk
The Tomcat people have kindly provided a page here which gives guidelines for compiling the connector. The problem is that the instructions on it don't seem to bare any relation to what you actually have to do! For all the people in this situation I will try and be as verbose as possible.
To build mod_jk you need to make sure you have the following packages installed: libtool, autoconf, gcc and apache2-prefork-dev which you can do with:
apt-get install libtool autoconf gcc apache2-prefork-dev
On a mature system you will probably only need the last one in that list which will probably require a number of other packages.
Note: A reader of this page reported that the configuration step will fail if g++ isn't installed. Installing g++ to fixes the problem. I haven't checked this (as I always have g++ installed) but this sounds fair enough. The failure message is given is a rather cryptic:
configure: error: C++ preprocessor "/lib/cpp" fails sanity check
Switch to the jk/native directory.
<DOWNLOAD_LOCATION>/jakarta-tomcat-connectors-jk-1.2.6-src/jk/native
Configure the connector with the following command. Note: this command is different if you are building the connector for Apache 1.3. You have to tell configure where apsx2 is located which you can discover with whereis apxs2 but I would be very surprised if the value shown below is wrong.
Note: A kind reader had pointed out that the original command (./configure --with-apxs=/usr/bin/apxs2 --with-apache=/etc/apache2) has a typo in it that when corrected causes the command to fail. The solution is to use one of the commands shown in the paragraph below.
jakarta-tomcat-connectors-1.2.14 seems can be configured using both the -with-apxs and --with-apache switches combined together. Running configure this way: "./configure --with-apxs=/usr/bin/apxs2" fixes this if you want to compile a shared module and "./configure --with-apache=/etc/apache2" if you want to compile a static module (use the first variation where possible).
You will see a hundred or so lines of output from the results of checking various system settings and whether certain tools are installed.
Now you have to make the module which is done quite simply with the command:
make
There will be a number of compiler warnings which AFAIK aren't a problem. Finally you have a choice of either running the command:
make install
Or copying the mod_jk.so file from in the apache2.0 sub-directory into /usr/lib/apache2/modules/. Either will work but if you copy the file you will probably have to manually alter the permissions to stop it being executable.
A reader pointed out that placing the mod_jk.so file in /usr/lib/apache2/modules/ isn't really the Debian way of doing things as this directory is under the control of the package manager. An alternative if you are worried by this might be /usr/local/lib/apache2/modules/. If you use this alternative path don't forget to update the path later in the tutorial as well.
Step 3 - Set up the Connector
I am going to try and copy the Debian standard way of configuring modules which will require three files to be created /etc/apache2/mods-available/jk.conf and /etc/apache2/mods-available/jk.load and finally /etc/apache2/workers.properties. The first one configures the module the second one loads it and the last one creates the workers. To activate the module you symlink the first two files into /etc/apache2/mods-enabled/.
The jk.load File
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
Yes it is just one line. Most of the load files are just a single line.
The jk.conf File
<IfModule mod_jk.c>
JkWorkersFile /etc/apache2/workers.properties
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel error
</IfModule>
Create the required symlinks in mods-enabled.
cd /etc/apache2/mods-enabled ln -s ../mods-available/jk.load . ln -s ../mods-available/jk.conf .
Create the workers file. This one I can't give you much help with as it is different depending on your requirements. The file below is about as simple as you can get though and will probably be fine for the vast majority of people (with obvious modifications). You might like to read this.
# Tomcat and Java configuration # workers.tomcat_home=/usr/local/tomcat workers.java_home=/usr/local/java ps=/ worker.list=foo # Definition for local worker using AJP 1.3 # worker.foo.type=ajp13 worker.foo.host=foo.com worker.foo.port=8009 worker.foo.cachesize=20
The last thing you need to do is setup your virtual host that will direct calls to the Tomcat server. A basic virtual host for this can be seen below. Virtual host definitions should be placed in /etc/apache2/sites-available/ and then symlinked to /etc/apache2/sites-enabled/. Alternatively put the definition in the default host definition.
<VirtualHost 81.5.183.106:80>
ServerName www.foo.com
DocumentRoot /usr/local/tomcat/webapps/foo
ServerAdmin webmaster@foo.com
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/foo.log combined
Alias / "/usr/local/tomcat/webapps/foo/ROOT"
<Directory "/usr/local/tomcat/webapps/foo/ROOT">
Options Indexes +FollowSymLinks
</Directory>
JkMount /* foo
<Location "/foo/WEB-INF/">
AllowOverride None
deny from all
</Location>
</VirtualHost>
Step 4 - Test it Works
The moment of truth - testing whether all that work has actually paid off. Start Tomcat with /usr/local/tomcat/bin/startup.sh and restart Apache (probably best to stop and then start). If all has gone well you should be albe to access webapps deployed in Tomcat.
Why Upgrade?
This instructions were written to cover the installation of the mod_jk module version 1.2.6 but, as I mentioned above, I have since repeated this with mod_jk version 1.2.13 so why have I done it? The answer is because this website requires some funky magic that isn't present in the 1.2.6 version. The magic of which I speak is the JkUnMount directive which allows you to specifically exclude certain resources from the JkMount search path. On most websites this probably wouldn't be that important but on this website it's vital and here is why. If you know much about Java web applications you will have spotted that the web application running this site is at the default context therefore any JkMount directive is going to start /* which is great except for the fact that there are other things living under this domain that I don't want to have to move to a subdomain such as users home directories (and various other things). Ok, I hear you say, why not just filter for just the jspx files in the JkMount directive like this /*.jspx. That sort of works but there is one big problem. This website used to be written in php and to save myself from loosing thousands of hits I wrote a little redirect filter that given one URL with 301 the user to the new URL. Clever eh? So to make this would I would need two JkMount directives /*.jspx and /*.php. Nothing wrong with that except that now anything else living under this domain that uses php ends up at Tomcat which is not what I want and it partially cripples the redirector because it will only ever see .php files. The solution is to upgrade to mod_jk 1.2.13 and use JkUnMount directives to unmount the applications that you don't want going to Tomcat. This means that the redirector will see all URLs that don't specifically match one of the other applications. The syntax for JkUnMount is the same as JkMount except for the name.