Table of Contents
Before you do anything, you need to decide what version of Tomcat you want to run. Consider the following factorys.
This guide covers only major versions 5.0.x and 5.5.x. I have no desire to use 4.x versions-- they suck. I look forward to using 6.x, but have had no opportunity to yet.
If your OS distribution comes with a Tomcat distro of a
version that you're satisfied with (or if your organization
provides one), then
you could simplify your life by using that... or not.
Otherwise, go to http://jakarta.apache.org
and download the latest stable (non-alpha and non-beta)
core binary of desired major version.
Just get the one Core file in the file format that you want
(For UNIX users, I recommend using that tar.gz format intead of
the zip. Otherwise you will need to make the script files
For version 5.0.x, get just the core download, which contains
the Manager and Admin web apps, and documentation.
For version 5.5.x, get the core download, which contains the
Manager web app and docs; plus the Admin download if you want to
run the Admin web app; and the JDK 1.4 Compat download if you
plan to use Java version 1.4.
(If you don't run the Admin web app, you will need to edit the
server.xml file manually for every
configuration change to the Tomcat server).
The Deployer download is not needed for a server install. This is not the Manager webapp, but a Java client for the Manager webapp. You install this on a workstation or server where you will run ant to deploy to the remote Tomcat server. (Not that you necessarily want to do that. It's overkill if you will only be deploying locally, and there are other ways to deploy remotely).
If you're using preconfigured packages, install them. Besides the base package, install packages for standalone docs, admin and manager webapps, samples webapp and docs webapp if you want them. It's a hard call whether to use OS-supplied Tomcat packages. The benefit is, upgrades are a snap, and can be automated, and, best of all, if your OS has packages for Apache HTTPD and a Tomcat plugin, 99% of the plugin setup is done for you.
You won't understand much of this document if you don't have a clear understanding of installation and instance.
A Tomcat installation is one set of all the stuff that you
extract from a Tomcat distribution (or packages, rpms, etc.).
You could very well have multiple installations on the same
server, for example, a Tomcat 5.5.9 installation and a Tomcat
There is no good reason to have multiple installations of the
exact same Tomcat distribution, since you can run as many
Tomcat instances as you want using one Tomcat installation.
The env variable
the tomcat installation root directory for the current environment.
A tomcast instance is a single Tomcat JVM (and also the set of
files specific to this tomcat instance).
People often use the word server for the
I try to use the word instance to avoid
any ambiguity with the other uses of server.
The env variable
the tomcat instance's root directory for the current environment.
conf/server.xml for each
CATALINA_BASE is where most of your
instance-based configurations are persisted, for example what
port to run on, where to write log files, etc.
The primary goal of the Admin webapp is to manage this file
(but most people edit it it manually instead).
Because of its importantce, you should take some time to study it.
The Tomcat documentation explains about half of it
The XML tags and attributes are named pretty intuitively.
One question that most people have when they look at it is,
What are all of those ports for?.
There is the main http port that will server your webapps to
browsers, SOAP clients, etc.
There is the Coyote port that will service plugin clients.
The AJP protocol is used between plugins and Tomcat, so you
can't use it for any other purpose.
There's also the shutdown port.
You can telnet to this port on localhost,
type SHUTDOWN and hit ENTER to shut down the instance.
Then there are SSL versions of these three ports (all of which
care commented out by default).
I recommend that you install the distro as the super-user, and leave everything from the distributions writable only to the superuser. After that you copy the small set of read-write files and open up write privileges for this set. This directory branch of instance-specific, writable, files is called the CATALINA_BASE for the instance. This is useful for a single-user system because when Tomcat gets screwed up (as it eventually will), it is very easy to start a new instance up (with its own CATALINA_BASE), or just wipe out your hosed CATALINA_BASE with a new copy from the distro. If you plan to run multiple Tomcat instances (for yourself or to be shared), then you definitely should use CATALINA_BASEs.
If you have superuser privileges, I recommend that you run your Tomcat instance as a dedicated non-privileged user. Unless you already have a tomcat account, create a user and group with name "tomcat".
cd to the parent directory of where you want your Tomcat
installation to live (parent directory because the extraction
will create one subdirectory which will contain everything).
Extraction will create a new subdirectory with name like
If you are installing 5.5.x, extract the Admin distro file
from the same place (if you want the Admin web app).
After you extract everything,
you can shorten the installation root directory name if you
like (I get along just fine without the "jakarta-" part).
A common practice on UNIX is to make a peer sym-link to the
"current" version with no version number in it, like
mv jakarta-tomcat-5.0.28 tomcat-5.0.28 ln -s tomcat-5.0.28 tomcat
CATALINA_HOME. Just to make the examples below really work, I'll assume that you set the environmental variable
CATALINA_HOMEto the absolute path of this directory.
Your CATALINA_HOME contains the following subdirectories.
Users installing the 5.5.x JDK 1.4 Compatibility distro should be aware that (at least for the versions I have installed), they use a different root directory name for the Compat bunlde, so you can't just overlay it on top of your core installation (like you can with the Admin distro). You'll need to extract the JDK Compat distro to a temporary location then copy it like so.
mkdir /tmp/tctemp cd /tmp/tctemp tar -xzvf /path/to/jakarta-tomcat-5.5.28-admin.tar.gz ... cd jakarta-tomcat-5.5.28-admin cp -a * $CATALINA_HOME ... cd rm -rf /tmp/tctemp
I recommend that you edit the
for the bundled default ROOT web app.
to make your site home page editable.
If you will always install your own ROOT web app (i.e., a web
app with context root of "/"), or will otherwise never use
Tomcat's default ROOT web app, just skip this paragraph.
Tomcat comes with a great default web app, with a great home page
with links to the bundled web apps and documentation.
It just makes sense to add your own links to this home page--
at least to the web apps that you install, but also perhaps
to application log file or external documentation.
Unfortunately, recent versions of Tomcat precompile the home
page JSP so that you editing the home page will have no effect.
The easy work-around for this is to edit the file
and just comment out the <servlet> and <servlet-mapping>
stanzas at the bottom.
This is a one-time customization.
Whenever you set up a
CATALINA_BASE from now on
(as described below), the home page for the instance will be
As described above,
CATALINA_HOME is where
you installed the Tomcat distribution to.
CATALINA_BASE will be the root directory of
your new instance.
Now make the CATALINA_BASE for your first (or only) Tomcat
instance by making a new CATALINA_BASE directory anywhere.
If you anticipate running multiple Tomcat instances, you may
want to make a new directory to be the parent to all of the
instances, then make the CATALINA_BASE within that.
For the purposes of my examples, I'll assume that you set the
CATALINA_BASE to the absolute path
of this directory.
Copy the five starred CATALINA_HOME subdirectories above to there.
Then set ownership to your instance owner and group.
Assuming that you've set variables
CATALINA_BASE, you can do it like this on UNIX.
mkdir $CATALINA_BASE cd $CATALINA_HOME cp -a conf logs temp webapps work $CATALINA_BASE chown -R tomcat.tomcat $CATALINA_BASE
mkdir %CATALINA_BASE% cd %CATALINA_HOME% xcopy /e /i /q conf %CATALINA_BASE%\conf xcopy /e /i /q logs %CATALINA_BASE%\logs xcopy /e /i /q temp %CATALINA_BASE%\temp xcopy /e /i /q webapps %CATALINA_BASE%\webapps xcopy /e /i /q work %CATALINA_BASE%\work
One difficulty you will have to live with if you're using
Linux Tomcat packages is, the actual instance files are spread
out all over the place, with sym-links from the CATALINA_BASE.
It's not all that difficult if you leave the default
CATALINA_BASE alone to use as a model.
For example, on Suse, it sets up a CATALINA_BASE named
base with CATALINA_BASE of
This CATALINA_BASE has sym-links to a config file under /etc,
log, temp, and work directories under /var, but a real webapps
Duplicate the same exact setup for your own instance, like
Make the webapps directory writable to whoever you want to permit to deploy by copying files into there.
chown -R deployer $CATALINA_BASE/webapps chmod gw+s $CATALINA_BASE/webapps
conf/*user*to people who can directly edit the main instance configuration file and the password file used by the bundled management webapps. But, Tomcat rewrites these files sometimes, so don't be surprised if the file attributes get changed on you.
If you followed my advice above, then you just repeat the CATALINA_BASE creation step above for each instance, then edit the server.xml file as described in the following subsection.
The Tomcat documentation says that you must edit the descriptors
for the bundled webapps.
That documentation is wrong, because the settings use filepaths
CATALINA_BASE, which works exactly
Dear reader, please make a detour now and read the introductory and Initial Instance Configuration sections of the Configuring Tomcat chapter. You really need to understand that material before consuming the remainder of this chapter.
Generally, you want to bundle needed jar files in your web app. That will avoid most dependency conflicts with other web apps, and reduces dependencies on things outside of the war file. For example, it won't matter if Tomcat or other web apps have the right version of a lib, because you have it yourself. It also means that your war will be more likely to run as-is on some other application server. The trade off is inefficiency of disk space and memory, when multiple wars bundle equivalent jar files. The inefficiency problems are trivial compared to the alternative.
Exceptions to the general rule are for the mail api and JDBC
In both cases, the exceptions are justified only so that you
can manage the mail and data source services as the app server
level as shared resources.
With Tomcat 5.5.x only, Tomcat doesn't bundle the email libraries
because of copyright laws.
(Ignore the rest of this paragraph if you're running a version an
earlier version, since it will include these two jar files).
Therefore, obtain the JavaMail and Activation Framework jars
and copy them into
These jar files are often named
(or the same with version numbers).
CATALINA_HOME/shared/classes and jars in
CATALINA_HOME/shared/lib are not added to
the runtime classpath, at least with Tomcat 5.5.x.
I think something broke, because these folders serve no purpose
without this behavior.
I know it used to be there, but there is no longer an explanation
of the purpose of the different Tomcat directories in the 5.5.23
Always use the
CATALINA_HOME/common branch for
shared resources, not
The other exception is JDBC drivers.
In the J2EE world, application servers have the responsibility
of managing data sources which apps look up via JNDI.
Therefore, if you are going to get your data sources by the
traditional J2EE method, you need to put your JDBC driver
jar files for your target database servers into
If you are not getting your datasources from
a JNDI lookup (regardless of whether there is an ORM, Spring, or
any other lay in between), then I recommend that you bundle your
JDBC libraries with your app (for the reasons given above) and
purposefully do not put them in any shared directory.
(If Tomcat is running when you change any files under
CATALINA_HOME/common/lib, you will need
to restart Tomcat for it to see the changes).
At least with Tomcat 4.x, Tomcat does not recognize zip files
in the the global
lib directories, only
.jar files. This isn't much of an issue nowadays since Oracle,
the last holdout, has finally stopped using zip files when they
should be using jar files.
I assume you're using an Apache HTTPD server (including branded Apache HTTPD servers, such as those by IBM and Oracle). If you're using some other web server, like IIS, you're on your own. I'm only documenting use of jk. Setup of other plugins is similar, but jk has the widest user base (by far), and is actively supported. The Apache HTTPD server is often just called the Apache server, even though Apache also makes the Tomcat server. To try to avoid this ambiguity without being too verbose, when I say httpd server in this section, I mean the Apache HTTPD server.
You can use the httpd server's mod_proxy module instead of a plugin. This is do-able, but has its own set of quirks, which I don't have time to document. I recommend that you use the most common setup-- the JK plugin-- unless you just can't get it to work. (The only valid reason I've encountered is that you have to support a version of httpd server for which you can't build the JK plugin).
Use pre-packaged binary distributions if at all possible, due to dependency requirements, which are detailed below.
Tomcat calls a network listener which connects clients to the
Tomcat engine a Connector.
(They probably want to avoid possible confusion with
lifecycle listeners, which are defined with
<Listener> tags in the
To get a possible point of confusion out of the way, be aware that all of the modern Tomcat connectors are Coyote connectors. All of the connectors you use will be Coyote connectors. (The SHUTDOWN network listener is not a Connector, since it does not connect to any Tomcat engine). Most significantly, when I speak of an HTTP connector or an AJP connector, I mean the Coyote HTTP or Coyote AJP connector, not some other, deprecated implementation. I point this out because this was apparently not the case in the past, since Tomcat documentation and config file comments imply some significance to "Coyote".
The only setup for the Tomcat side is to enable the AJP 1.3,
and that will already be enabled unless you deleted or commented
it out from your template
However, read this section to make sure that it is running, and
to find out what network target to have your Apache plugin connect
If something else is occupying the default AJP 1.3 listener port
(perhaps another Tomcat instance), you will need to change the
port number (see the
Configuring Tomcat chapter
for tips about finding available ports).
Take a look at
Search for all uncommented <Connector> tags.
By default, there will only be two, one HTTP connector and one
AJP 1.3 connector: search for "AJP/1.3".
Both of the Tomcat-supplied
have misleading comments about this element, so just ignore them.
I will be calling this connector the AJP connector, since we are
only concerned with AJP version 1.3, and the connector just
serves AJP and doesn't mandate that the client be JK,
JK2, or anything else (you can write your own AJP 1.3 client).
Note the port number for the AJP connector.
I suggest that you remove the voluminous commented examples of
SSL connectors-- it clutters the file up with crap that you will
When I talk about Apache configuration directives, I will give
the Apache 2 module variant.
See your docs if you are running some other Apache variant.
In all cases, you can track down all Apache config files by
recursively following the includes from the main
(which latter filepath has a compiled-in default which can be
overridden on the httpd command line
or use a compiled-in default).
httpd-server-side Plugin Configuration
This can be the most difficult step of all.
The .so binary must compatible with your version of Apache and
it must use the same version of AJP as your Tomcat distribution.
(If you are following these instructions, the second dependency
will be taken care of if you just stick to AJP version 1.3).
The shared library will be called something like
Hopefully, your can get a pre-built binary with your Apache
or OS distribution.
Otherwise, download the source and build it, according to the
very detailed instructions--- good luck.
Stick the .so file into the same directory
as all of your other native Apache module libraries.
Suse users can find
mod_jk.so in the
mod_jk-ap20 (in the latter name, the
20 means that it is for Apache version 2.0).
Building is not difficult on Linux if you have a the Apache 2 developer rpm (including apxs version 2) and gcc. It can be incredibly difficult on other UNIXes.
You must set the worker properties.
If you are running JK version 1.2.7 or later, you can set them
in your httpd server config file (exactly as described in the
following section) with
All versions may make these settings in a
workers.properties file, and
that is what I explain here
(only because most binary distributions which I encounter
are always pre-1.2.7; and for most distributions, you
can't even tell the JK version number).
If you have version 1.2.7 or later, I recommend you use
JkWorkerProperty-- read this section, but
make the corresponding
JkWorkerProperty as explained in the next
SuSE v. 9.3 and 10.0 both have version 4.1.30 of mod_jk-ap20, which contains a beta of JK version 1.2.6. Can you believe that shit? A year and a half old, and they can't even use a production cut.
This file defines the Tomcat server destinations that you can route to from your httpd server instance. You assign each Tomcat server destination a worker name, and you can then use that name to redirect specific request URLs from the httpd server to this Tomcat worker instance (as described in a following step).
Like I said, the
just needs to define the Tomcat worker instances which you
want to make available to your httpd server instance.
If you have a sample file, just wipe it out, because in the
great majority of cases, you only need four lines.
(Most JK distributions come with a sample file filled with
inappropriate settings... you're better off without the
Example 2.1. workers.properties file
worker.list=tomcatWorker1 worker.tomcatWorker1.port=8009 worker.tomcatWorker1.host=localhost worker.tomcatWorker1.type=ajp13
server.xml(which is explained above). If you have a distributed, load-balancing setup, see the docs about additional settings, and the Tomcat docs about the
Most documentation which I can find instructs to place the
That is a stupid place to put this file, since (a) the file
is read by httpd server, not Tomcat, and
(b) If you have a distributed setup, this file must
accompany your httpd server instances, not any Tomcat instance.
The Tomcat JK docs give the false impression that the
workers.properties is part of the Tomcat
configuration (as definitely proven by the fact that with
recent versions, the functionality can be taken over entirely
by using httpd server directives).
These settings all need to go into httpd server config
file(s), either a main
or a file included directly or indirectly.
Which file(s) you put them into depends upon whether you
want the settings shared by all virtual servers or not,
and by the fact that some global settings must appear
before site-specific settings.
I recommend that put your global settings directly in
httpd.conf, and all other settings
directly wherever your (virtual) site-specific settings
like DocumentRoot are.
To get JK working with other virtual hosts, just duplicate
the vhost-specific settings you made for your first vhost.
Attention name-based virtual host users.
This has nothing to do with Tomcat specifically, but it is
something that is very non-intuitive for standard httpd
name-based server setups.
httpd.conf delivered with
many Apache 2 distributions includes a
default-server.conf file which works
fine, but not if you use name based hosts.
The reason is, this file has useful settings for
documentRoot, etc, but, since they are not in a virtual
host block, they will always be overridden by your first
virtual host definition (which default host is determined
alphabetically with the default setup).
For security alone, you should not send users to a random
What a sane person would want to happen is that requests
for URLs which match no defined virtual host name should
use the settings in the
You can accomplish this easily and elegantly by defining
a default VirtualHost before
including your virtual host files.
Just insert the following directives after the
and before the
Example 2.2. Make the default-server config the default virtual host
NameVirtualHost *:80 <VirtualHost *:80> # Just inherit all the settings in /etc/apache2/default-server.conf </VirtualHost>
You need to load the JK module with a directive like
LoadModule jk_module /usr/lib/apache2/mod_jk.so,
specifying the filepath to the native library file.
This is a global level setting, since you just load the
module one time, regardless of how many virtual sites or
Tomcat worker instances you have.
(Suse user be aware the Suse has an idiotic system where
they rebuild the LoadModule directives dynamically. You
set the variable
APACHE_MODULES, in the
/etc/sysconfig/apache2, to the
base names for all modules, with the assumption that the
native library files all reside in the normal directory,
and are named according to the supplied module name.
You need to specify the path to the
workers.properties file, like
This is a global level setting, since you just need tone
workers file for an entire httpd server (because one
workers file can define any number of Tomcat worker target
If you are not using
file (see previous step), then, instead of a
JkWorkersFile directive, give a
JkWorkerProperty directive for each
worker property you need (which are described in the
previous section--- for example,
You need to specify the path to the log file for the
httpd-server-side of JK, like
You can specify a logging level of
error, if the default level of
info doesn't suit you.
Tell httpd server to serve all static webapp content
The httpd server must have access to the exploded webapp
files to serve them directly
(i.e., they must reside on the physical httpd server in
exploded-- not war file-- state, and must be readable to
the httpd server process owner).
Most importantly, you must use
directives to cover all of the webapp directories, so
that httpd can serve them.
You need the Directory directives regardless of how you
graft onto the URL tree.
If you have Tomcat and httpd server running on the same
server, then give a
directive to tell the httpd server to automatically graft
all webapp directories into the httpd URL namespace and
serve them directly.
The JkAutoAlias directive is just an alternative to giving
Location and DocumentRoot directives for the different
webapp directory branches.
If you only want Apache to serve static content from a
subset of the Tomcat webapps, then use normal Location and
DocumentRoot directives instead of JkAutoAlias.
If Tomcat is running on a different physical server, then
you will have to explode all of the wars on the httpd
server computer and then use one of the two methods above
to serve these directories.
(The JkAutoAlias just requires that the webapps all reside
in one parent directory).
You should understand that nothing in this paragraph will
cause any interaction with Tomcat, it just tells Apache
to serve some stuff in normal non-Tomcat fashion.
The next paragraph tells how to forward requests on to
The JkAutoAlias does not know about the root context
Therefore, requests for
not map to
which would be the desired thing to do.
JkAutoAlias is really useless for a default context
You'll have to use other Apache directives to serve it.
JkAutoAlias is smart enough to never serve information from underneath WEB-INF of your webapps.
If you get an error upon UNIX startup about the command JkUnMount, then you probably have an ancient jk_mod binary. Either live without JkUnMount, or obtain or build a recent JK library.
Tell Apache which URLs to forward to Tomcat with the
Both take a URL pattern and a Tomcat worker instance name.
JkUnMount commands take precedence over JkMount commands,
regardless of the sequence in which they appear.
Here's an example that shows both commands.
JkMount /servlet/* tomcatWorker1 JkUnMount /servlet/*.gif tomcatWorker1
http://hostname:port/servlet/will not be forwarded to Tomcat, due to the higher precedence of JkUnMount commands.
Some JK distributions put samples of these settings into a
jk.conf, or similar.
In most cases, this discourages effective directive sharing
among multiple virtual servers.
When running with multiple virtual servers, some directives
should be made just once for the entire server, other
settings should be duplicated for each virtual server, and
others require unique settings for each virtual server.
Since we are talking about a total of about four
sharable directives, in nearly all cases it's simpler and
more effective to just put each directive directly into
the desired virtual-site-specific or main
The actual URL-mapping directives, which comprise 90% of
the needed directives, are
virtual-server specific and can't be shared at all.
Example 2.3. Typical httpd.conf directives
# These toward the top in the main httpd.conf file LoadModule jk_module /usr/lib/apache2/mod_jk.so JkWorkersFile /etc/apache2/workers.properties # These in virtual-server specific files, or with other site-specific # settings like DocumentRoot and site-specific log file settings. JkLogFile /var/log/tomcat5/base/mod_jk.log JkLogLevel error JkAutoAlias /opt/tomcat/webapps # Then specify all URL patterns to pass to Tomcat JkMount /servlet/* tomcatWorker1 JkMount /*.jsp tomcatWorker1 JkUnMount /*/WEB-INF/* tomcatWorker1
Use of a Webapp Staging Directory avoids polling race condition
problems if you deploy webapps by manually copying or moving
files into the Tomcat
The problem occurs because Tomcat monitors the
webapps directory and the first time it sees
a new entry, it decides right then whether it will henceforth
consider this entry a war file, a web app directory, or ignore it.
If it looks at the directory or war file before it contains the
file (because the copy has not reached that point yet),
then it won't attempt to deploy it at all and will ignore the
whole thing from this point forward.
If it sees the
web.xml, then it will attempt
to deploy. If your copy has not finished, it will deploy only
a portion of your webapp and will never finish it.
The solution to this problem is to not copy
anything into the
webapps directory, but to
move to there from the same filesystem
From Tomcat's perspective, the move is an atomic operation.
Before the move completes, it won't see the new item at all.
After the move completes, the entire webapp is available for
The only real requirement for this to work is that you
move the webapps/war from another directory
in the same filesystem partition.
If you work with multiple servers, then I highly recommend that
you make a staging directory right under
webapps specificaly for this purpose. For
purposes of this document, I'll assume it is
No matter what server you're on, you'll know that the staging
directory is in the same partition as
and it's really convenient to be able to cd to
webapps and deploy and undeploy web
applications with short commands like
cd $CATALINA_BASE/webapps mv appToUndeploy stage mv warToUndeploy stage mv stage/appToDeploy