Anda di halaman 1dari 33

Tomcat Howto

Blaine Simpson

Tomcat Howto
Blaine Simpson Published $Date: 2007/07/15 14:54:46 $

Table of Contents
1. Introduction ............................................................................................................ 1 Available formats for this document ....................................................................... 1 Purpose ............................................................................................................. 1 Support ............................................................................................................. 1 Tomcat Versions Covered/Recommended ................................................................ 2 Changing Tomcat Versions ................................................................................... 2 2. Tomcat Installation .................................................................................................. 3 Distributions ...................................................................................................... 3 Tomcat Instances ................................................................................................ 3 Install ............................................................................................................... 4 Setting up Multiple Instances ................................................................................. 6 Configuration ..................................................................................................... 7 Shared Jar Files .................................................................................................. 7 HTTPD-to-Tomcat Plugins ................................................................................... 7 Tomcat-side Plugin Configuration .................................................................. 8 httpd-server-side Plugin Configuration ............................................................ 8 Webapp Staging Directory .................................................................................. 13 3. Starting a Tomcat Instance ....................................................................................... 14 Init script ......................................................................................................... 14 4. Tomcat-Bundled Web Apps ..................................................................................... 16 Manager Webapp details .................................................................................... 16 Admin Webapp details ....................................................................................... 16 5. Configuring Tomcat ............................................................................................... 18 Initial Instance Configuration .............................................................................. 19 server.xml ................................................................................................ 19 tomcat-users.xml ....................................................................................... 19 server.xml ................................................................................................ 19 System Properties .............................................................................................. 19 Final Setup ...................................................................................................... 20 J2EE Resources ................................................................................................ 20 Authentication user/role lists ............................................................................... 21 Data Sources .................................................................................................... 21 Logging .......................................................................................................... 21 6. Securing Tomcat's Administrative Web Apps .............................................................. 22 7. Tomcat Deployer Client .......................................................................................... 24 8. Tomcat Quirks ...................................................................................................... 25 Typical run-time failures .................................................................................... 25 Deployment failures .......................................................................................... 25 Manager webapp Quirks ..................................................................................... 25 Administrative App Quirks ................................................................................. 26 Manual deployment failures ................................................................................ 26 Tomcat is stuck! ............................................................................................... 26 Tomcat won't shut down! .................................................................................... 27 Email Config Problems ...................................................................................... 27

iv

List of Tables
1.1. Alternate formats of this document ........................................................................... 1

List of Examples
2.1. workers.properties file ............................................................................................ 9 2.2. Make the default-server config the default virtual host ................................................ 10 2.3. Typical httpd.conf directives ................................................................................. 12 3.1. Multi-Tomcat-instance generic UNIX init script ........................................................ 14 6.1. SSL Connector Element ....................................................................................... 22 6.2. web.xml Element requiring SSL ............................................................................. 23

vi

Chapter 1. Introduction
If you notice any mistakes in this document, please email me at blaine.simpson@admc.com [mailto:blaine.simpson@admc.com?subject=tomcat%20Howto] so that I can correct them. You can also email me if you have problems with the procedures explained herein, or if you have questions, comments, suggestions or complaints.

Available formats for this document


This document is available in several formats. You may be reading this document right now at http://admc.com/blaine/howtos/tomcat, or in a distribution somewhere else. I hereby call the document distribution from which you are reading this, your current distro. http://admc.com/blaine/howtos/tomcat hosts the latest versions of all available formats. If you want a different format of the same version of the document you are reading now, then you should try your current distro. If you want the latest version, you should try http://admc.com/blaine/howtos/tomcat. Sometimes, distributions other than http://admc.com/blaine/howtos/tomcat do not host all available formats. So, if you can't access the format that you want in your current distro, you have no choice but to use the newest version at http://admc.com/blaine/howtos/tomcat.

Table 1.1. Alternate formats of this document


format your distro at http://admc.com/blaine/howtos/to mcat http://admc.com/blaine/howtos/tom cat/index.html http://admc.com/blaine/howtos/tom cat/tomcat.html http://admc.com/blaine/howtos/tom cat/tomcat.pdf

Chunked HTML

index.html

All-in-one HTML

tomcat.html

PDF

tomcat.pdf

Purpose
I'm writing this document because I pity the huge number of people who waste tons of time (1) trying to learn how to use Tomcat effectively without any guide to tell then which of the reams of Tomcat documentation is meaningful for typical use; and (2) trying to find out what is going wrong when they run into any of the many Tomcat bugs and quirks. It takes a lot of time to assemble a document like this, but, considering that I get asked questions about Tomcat use continuously, I may just end up netting a net savings on my time by writing this.

Support
1

Introduction

First off, if you have a running Tomcat instance, install the Tomcat documentation web app if you haven't already. The API specs are great for development. The user and configuration docs will sometimes have what you need, but it seems that they always explain only one narrow example of each issue, and leave all other setups entirely unaddressed. There are lots of forums out there for Tomcat. Unfortunately, one of the main reasons I'm writing this document is, about 90% of the time when I search for help about a Tomcat bug or quirk, more often than not I find a bund of people who have the same question I have (on mailing lists and forums), and either no answers, evasions by Tomcat developers, or wild guesses by ignorant people trying to be helpful. If you want my personal help, email me at blaine.simpson@admc.com [mailto:blaine.simpson@admc.com?subject=tomcat%20Howto]. If you want hours of my time, I'm available for contractual work. I can set up integrated shared development, staging, and production environments with CVS/Subversion/RCS, database, ant builds, etc., complete with hardcopy and online manuals (similar in format to what you are reading). I also like to give classroom instruction on lots of Java topics, including Tomcat.

Tomcat Versions Covered/Recommended


I cover the 5.0.x and 5.5.x series of Tomcat, unless otherwise specified. I usually use the 5.0 series if I have to use Java 1.4, because I find that 5.5 is unstable when run with the 1.4 Compatibility add-on (at least with large and/or troublesome web apps). If you're running Tomcat 4.0 (or earlier), I suggest that you spend your time migrating to a better version instead of wasting time working around limitations and bugs that have already been fixed. I have personally experienced the extreme pain involved when trying to limp along with an ancient version of Tomcat many times. Besides the Jakarta community ignoring your support needs, limitations, and bugs, the old Tomcats have dependences upon old versions of third party libraries (like Jakarta commons, log4j, XML, etc.), and this leads, all too often, to the most frustrating kind of library conflicts. If you are are required to use some tool that requires some old version of Tomcat, then your problem is a sucky tool. In that case, I recommend that you ignore the recommendations of the crappy tool vendor and spend a little time installing a new Tomcat distro and maybe packing some legacy libraries in with your tool to make it run.

Changing Tomcat Versions


If you change a minor version, just shut down your instances, set CATALINA_HOME to your new Tomcat installation, and start up your instances. If you are changing a major version, e.g., changing from a 5.0.x to 5.5.x or 4.x, then you need to convert your configuration files. Start with a fresh set of config files from the new distribution and merge in customizations from your old configuration files.

Chapter 2. Tomcat Installation


Distributions
Before you do anything, you need to decide what version of Tomcat you want to run. Consider the following factorys. Conformance levels of Servlet spec, JSP spec, JDK version support, etc. Stability. In my experience, the 5.0 series is most stable. Generally stay current. If you are running a version that many other people run, it's easier to get Internet support for Tomcat itself as well as third party products with Tomcat, and third party libraries are more likely to work more likely to work right Requirements of your organization. Availability of pre-configured distributions. I.e., software distributions, perhaps customized, by your organization or your operating system vendor.

Note
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 executable). 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.

Tomcat Instances
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, 3

Tomcat Installation

rpms, etc.). You could very well have multiple installations on the same server, for example, a Tomcat 5.5.9 installation and a Tomcat 5.0.28 installation. 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 CATALINA_HOME identifies 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 same purpose. I try to use the word instance to avoid any ambiguity with the other uses of server. The env variable CATALINA_BASE identifies the tomcat instance's root directory for the current environment. The file 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 well. 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).

Install
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 a set of 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 nonprivileged 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 jakarta-tomcat-5.0.28. 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 This directory is your CATALINA_HOME. Just to make the examples below really work, I'll assume that you set the environmental variable CATALINA_HOME to the absolute path of this directory. Your CATALINA_HOME contains the following subdirectories. bin 4

Tomcat Installation

common conf* logs* server shared temp* webapps* work*

(Each Tomcat instance gets a copy of the starred directories. The remaining directories are shared among all Tomcat instances). 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 Overwrite all files if prompted by your copy command. I recommend that you edit the web.xml 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 CATALINA_HOME/webapps/ROOT/WEB-INF/web.xml 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 editable. 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 example .../tomcat-intances/balder1. For the purposes of my examples, I'll assume that you set the variable 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_HOME and CATALINA_BASE, you can do it like 5

Tomcat Installation

this on UNIX.

mkdir $CATALINA_BASE cd $CATALINA_HOME cp -a conf logs temp webapps work $CATALINA_BASE chown -R tomcat.tomcat $CATALINA_BASE Assuming that you've set the same Windows environment variables, and that we're just working with one disk drive, on modern Windows you do it like this.

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

Tip
One way to set environmental variables in modern Windows operating systems is by using menus Windows / Start / Control Panel / System, Advanced tab, Environment Variables button, New button under System variables. 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 /srv/www/tomcat5/base. This CATALINA_BASE has sym-links to a config file under /etc, log, temp, and work directories under /var, but a real webapps directory. Duplicate the same exact setup for your own instance, like / srv/www/tomcat5/yourinstance. 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 (Understand that if you use the Manager webapp for remote deploys, the deployed objects, normally wars, will have the user and group of the Tomcat process, not of the remote user, and the final file permissions will depend on how you do the remote deployment.) You may want to change permissions on the files conf/server.xml and or 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.

Setting up Multiple Instances


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 docu6

Tomcat Installation

mentation is wrong, because the settings use filepaths relative to CATALINA_BASE, which works exactly as needed.

Configuration
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.

Shared Jar Files


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 drivers. 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 CATALINA_HOME/common/lib. These jar files are often named mail.jar or mailapi.jar and activation.jar or jaf.jar correspondingly (or the same with version numbers).

Warning
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 docs. Always use the CATALINA_HOME/shared/classes branch for shared resources, not CATALINA_HOME/common 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 CATALINA_HOME/common/lib. 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.

HTTPD-to-Tomcat Plugins
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 7

Tomcat Installation

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.

Note
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 server.xml> file). 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".

Tomcat-side Plugin Configuration


The only setup for the Tomcat side is to enable the AJP 1.3, Connector, and that will already be enabled unless you deleted or commented it out from your template server.xml file. However, read this section to make sure that it is running, and to find out what network target to have your Apache plugin connect to. 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 CATALINA_BASE/conf/server.xml. 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 server.xml files 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 never use.

httpd-server-side Plugin Configuration


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 httpd.conf file (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


native shared libarary This can be the most difficult step of all. The .so binary must 8

Tomcat Installation

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 mod_jk.so. 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 rpm apache2-jakarta-tomcat-connectors or 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. workers.properties 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 JkWorkerProperty directives. 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 forget the workers.properties and make the corresponding JkWorkerProperty as explained in the next section.

Note
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 workers.properties file 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 sample).

Example 2.1. workers.properties file


worker.list=tomcatWorker1 worker.tomcatWorker1.port=8009 9

Tomcat Installation

worker.tomcatWorker1.host=localhost worker.tomcatWorker1.type=ajp13 You should see that we have defined the destination Tomcat instance tomcatWorker1. All of the worker.WORKERNAME.* settings must match the settings for that Connector in your Tomcat 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 server.xml jvmRoute setting..

Note
Most documentation which I can find instructs to place the workers.properties under CATALINA_BASE. 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). Apache Runtime Directives These settings all need to go into httpd server config file(s), either a main httpd.conf, 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.

Tip
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. The default 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 site accidentally. 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 default-server.conf file. 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 Include /etc/apache2/default-server.conf and before the Include / etc/apache2/vhosts.d/*.conf.

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 10

Tomcat Installation

</VirtualHost> The critical point here is to insert it at the location specified. 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 file / 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 JkWorkersFile / etc/apache2/workers.properties. 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 instances). If you are not using workers.properties 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, JkWorkerProperty worker.tomcatWorker1.port=8009. You need to specify the path to the log file for the httpd-server-side of JK, like JkLogFile / var/log/tomcat5/base/mod_jk.log. You can specify a logging level of trace, debug, warn, error, if the default level of info doesn't suit you. For example JkLogLevel error. Tell httpd server to serve all static webapp content directly. 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 Directory 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 JkAutoAlias 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 11

Tomcat Installation

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 Tomcat.

Caution
The JkAutoAlias does not know about the root context web app. Therefore, requests for http://hosthame:port/file.txt will not map to WEBAPPDIR/ROOT/file.txt, which would be the desired thing to do. JkAutoAlias is really useless for a default context webapp. You'll have to use other Apache directives to serve it.

Note
JkAutoAlias is smart enough to never serve information from underneath WEB-INF of your webapps.

Note
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 JkMount and JkUnMount directives. 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 In this case, requests for requests of the form http://hostname:port/servlet/ will not be forwarded to Tomcat, due to the higher precedence of JkUnMount commands.

Note
Some JK distributions put samples of these settings into a file named 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 httpd.conf file. 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

12

Tomcat Installation

# 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 oth # settings like DocumentRoot and site-specific log fi 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

Webapp Staging Directory


Use of a Webapp Staging Directory avoids polling race condition problems if you deploy webapps by manually copying or moving files into the Tomcat webapps directory. 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 web.xml 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 partition. 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 deployment. 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 $CATALINA_BASE/webapps/stage. No matter what server you're on, you'll know that the staging directory is in the same partition as webapps, and it's really convenient to be able to cd to webapps and deploy and undeploy web applications with short commands like cd mv mv mv $CATALINA_BASE/webapps appToUndeploy stage warToUndeploy stage stage/appToDeploy

13

Chapter 3. Starting a Tomcat Instance


There are lots of quirks which are encountered when trying to start up Tomcat. See the Tomcat Quirks chapter about problems with starting up Tomcat. If you are restarting Tomcat, make sure that it really does shut down, because the Tomcat-supplied scripts do not tell you if your shutdown attempt fails. Often, a startup problem is really a shutdown problem... if you could just stop the damned thing, it would start just fine. See the Tomcat Quirks about fixing that.

Init script
If your OS supplies a good init script, you should probably use that, since it will probably use configuration files and users which have been set up by the OS-specific installation scripts. Suse-users should be aware that most of the runtime configurations for the startup script are made in / etc/sysconfig/j2ee. Most significantly, the setting CATALINA_BASE.

Example 3.1. Multi-Tomcat-instance generic UNIX init script


#!/bin/sh -p # $Id: tomcat,v 1.8 2005/11/01 15:32:16 blaine Exp $ export CATALINA_HOME CATALINA_BASE JAVA_HOME CATALINA_PID JAVA_OPTS BASE_PARENT_PATH=/home/tomcat DFLT_CATALINA_HOME=/usr/local/tomcat-5.0.28 DFLT_JAVA_HOME=/usr/local/java DFLT_TOMCAT_OWNER=tomcat # Note: Set JAVA_OPT to increate RAM usage, etc. # The "headless" setting is needed for any webapps making use of # an awt graphics context, like with JFreeChart or JasperReport. DFLT_JAVA_OPTS="-Djava.awt.headless=true -ms512M -mx512M" case "$1" in start|stop) case "$1" in start) SCRIPT=startup.sh;; stop) SCRIPT=shutdown.sh;; esac for catworkdir in $BASE_PARENT_PATH/*/work/Catalina; do workdir=`dirname $catworkdir` CATALINA_BASE=`dirname $workdir` [ -d "$CATALINA_BASE" ] || { echo "Aborting. CATALINA_BASE '$CATALINA_BASE' not a directory?" 1>&2 exit 1 } # Reset all vars to defaults CATALINA_HOME="$DFLT_CATALINA_HOME" JAVA_HOME="$DFLT_JAVA_HOME" TOMCAT_OWNER="$DFLT_TOMCAT_OWNER" JAVA_OPTS="$DFLT_JAVA_OPTS" BASE_NAME=`basename $CATALINA_BASE` case "$BASE_NAME" in test*) continue;; template*) continue;; esac CATALINA_PID=$CATALINA_BASE/temp/tomcat.pid # Allow instance-specific environment file to override any settings [ -f "$CATALINA_BASE" ] && [ -r "$CATALINA_BASE/instance.env" ] && 14

Starting a Tomcat Instance

. "$CATALINA_BASE/instance.env" echo "Starting Tomcat instance '$BASE_NAME'..." 1>&2 if su "$TOMCAT_OWNER" -c $CATALINA_HOME/bin/$SCRIPT; then echo Success else echo Failed fi 1>&2 done ;; purge) /etc/init.d/tomcat stop || exit 1 for catworkdir in $BASE_PARENT_PATH/*/work/Catalina; do workdir=`dirname $catworkdir` CATALINA_BASE=`dirname $workdir` [ -d "$CATALINA_BASE" ] || { echo "Aborting. CATALINA_BASE '$CATALINA_BASE' not a directory?" 1>&2 exit 1 } BASE_NAME=`basename $CATALINA_BASE` case "$BASE_NAME" in test*) continue;; template*) continue;; esac echo "Purging Tomcat instance '$BASE_NAME'..." 1>&2 rm -r $CATALINA_BASE/logs/* done exec /etc/init.d/tomcat start ;; restart) /etc/init.d/tomcat stop && exec /etc/init.d/tomcat start ;; *) echo "SYNTAX: /etc/init.d/tomcat {start|stop|restart|purge}" 1>&2 exit 2 ;; esac exit 0 You can download it here [tomcat]. Explain settings for my Tomcat init script.

15

Chapter 4. Tomcat-Bundled Web Apps


You should understand that Tomcat comes with some web apps installed in the $CATALINA_BASE webapps directory, and some installed to a shared location and referenced by a context XML file under $CATALINA_BASE/conf/Catalina/localhost. The Tomcat Manager web app lists all installed web apps. Most importantly, become familiar with the Tomcat Manager web app. There are a couple quirks to it, but it's a great way to check on your web apps and to interactively start, stop, and deploy them. If you do a normal install, all you need to do to use the manager web app is to edit $CATALINA_BASE/config/tomcat-users.xml to add a record for a user with role "manager". Then (unless you have removed or replaced the ROOT web app), go to the home page and click on the link for Tomcat Manager. If you don't have the default ROOT web app in place, then use the URL http://yourhost:XXX/manager/html (replace XXX with the port you are running on).

Manager Webapp details


The Manager uses the <display-name> from web.xml as the web application titles, not the <description>. There is no "re-deploy". You have to "Undeploy" then "Deploy" again. To deploy a war file local to Tomcat, you must specify "WAR... URL" like jar:file:/path/to/bar.war!/ If everything is ok, context root will be "/filebasename" and the app will be started. See the Tomcat Quirks chapter about quirks. The Tomcat Administration web app is often useful. You can use it to manage shared server resources such as ACLs, user lists, data sources, mail servers. Unfortunaly, the app isn't really production-ready, and most of the functionality is highly dependent upon exactly how you have your shared resources set up. If you do a normal install, all you need to do to use the manager web app is to edit $CATALINA_BASE/config/tomcat-users.xml to add a record for a user with role "admin". Not sure about 5.0.x, but with 5.5.x, your server.xml file must contain the four Admin webapp LifecycleListener <Listener> tags, which you can copy from one of the supplied sample server.xml files.

Admin Webapp details


I sure wish I had time to make the Admin Webapp reliable and consistent, because what works is really useful. Many operations will get screwed up if you don't let them complete before doing something else, so always pause after making significant changes or Committing. Some operations cause the Admin webapp itself to restart, and you will have to log in again (without any indication of why). Many changes will not take effect until you restart Tomcat, but a few are effective immediately (like changes to valves). Many changes require Committing to persist them, but several do not (like User and Role changes). See the Securing Tomcat's Administrative Web Apps chapter to learn my suggested method to secure your administrative web apps in a simple and efficient way. The jsp-examples, servlets-examples, and tomcat-docs web apps are immensely useful 16

Tomcat-Bundled Web Apps

to have on-hand for day-to-day J2EE developerment. Leave these apps running on your development servers! I don't know anybody who uses Tomcat clustering or load balancing. I'm not discouraging anybody from using these features, but if this server is a development server, you don't need load balancing, or you are using some other product for these goals, then use the Manager web app to Undeploy the are not going to use them, then balancer and host-manager web apps. In fact, I have no idea what the hostmanager web app does, but everything runs fine without it. It would be great if the Tomcat team would give some clue about its purpose in the Tomcat documentation.

17

Chapter 5. Configuring Tomcat


I know of no application server that is hands off. Whether commercial or open source, your success with an application server depends direcly upon how well you understand the configuration facilities. For Tomcat, this means you must be able to edit the following files. CATALINA_BASE/conf/server.xml Primary configuration for the Tomcat server instance at this CATALINA_BASE. This contains critical settings like what port to run on, what protocols to serve, plugin configuration, many other things. CATALINA_BASE/conf/Catalina/localhost/*.xml and CATALINA_BASE/webapps/*/META-INF/context.xml External <Context> elements, exactly the same as <Context> elements inside the server.xml instance at this CATALINA_BASE. These contain all of the Tomcat-specific settings for one web application. If you are looking for the Tomcat-specific settings for a web app, you need to look for a <Context> element in server.xml; and in a file named CATALINA_BASE/conf/Catalina/localhost/<APPNAME>.xml for apps installed with a .war file or CATALINA_BASE/conf/Catalina/localhost/<APPNAME>.xml for apps installed in exploded directory format. Some of the things found here are JNDI mappings for the application, access control lists, access log setup, deployment modes like auto-redeploy. CATALINA_BASE/conf/tomcat-users.xml The username/role list used by default for accessing the Management and Administration web apps, as well as any of your apps which use the default Memory Based Realm for authentication. CATALINA_BASE/conf/tomcat-users.xml Simple text file describing roles and users for the Tomcat-supplied web apps, and any of your web apps which wish to use it.

There are Gui web apps to help with many of the common settings, but I guarantee that at some point you will encounter problems which require manual examination or editing of the files above. As a consolation, while the structure of these files is far from straight-forward, they are far more simple than in any other app server which I have seen. Even my favorite commercial app server, WebSphere, suffers from overly complex configuration due to the business case to support (almost) every option graphically. It's usually best to put your Tomcat application settings into a context.xml file instead of in server.xml. You bundle the context.xml file in the META-INF directory under the root of your web app. If you deploy your application as a war file (as opposed to writing the exploded directory right under CATALINA_BASE/webapps), Tomcat will automatically move the file to CATALINA_BASE/conf/Catalina/localhost/<APPNAME>.xml and will use it from there.

Tip
If you are running Linux (or Cygwin with the Net/inetutil package), it's very useful to run "netstat -tln" and grep for your SHUTDOWN and connector ports. The default settings for the SHUTDOWN, HTTP, and AJP ports all begin with "80", so this works great for a default setup:

netstat -lnt | grep :80

18

Configuring Tomcat

Initial Instance Configuration


server.xml
Do all of this while Tomcat is not running. Tomcat itself writes to these files, so don't risk it. After installing a new CATALINA_BASE, you need to decide what to use as your starting server.xml. Basically, do you want to start with the default server.xml which has a ton of comments, or a stripped down version, server-minimal.xml. I recommend that you use the last. To use server-minimal.xml, remove server.xml and rename server-minimal.xml to server.xml. (If you want to use templates from the original server.xml, you can always copy and paste from $CATALINA_HOME/conf/server.xml). If you are going to use a httpd plugin, leave the AJP/1.3 Connector element in place, otherwise wipe it out. Unless you want to manually edit server.xml and tomcat-users.xml for all future changes, make sure the four<Listener> elements for the Admin server are active. If you started with the minimal file, you'll need to copy and paste these from $CATALINA_HOME/conf/server.xml to right under your opening <Server> tag. Most users will use any SSL on their Tomcat server, except for securing the administrative web apps (I cover this use case in a different section). If you need to encrpyt some content, and you either aren't running an httpd front end, or the httpd server is on another host without a secure channel, you will need to set up SSL connectors. Make sure that all ports specified by active attributes are available. A port is not available if it is in use by a different Tomcat instance, or by anything else. If not, change the numbers to available ports. Ports below 1024 are only available to privileged users.

tomcat-users.xml
If you will use neither administrative web app, and you don't want to use this user database realm for your own applications, you should wipe out the UserDatabase portions from server.xml and ignore the tomcat-uses.xml file. Otherwise, wipe out all of the <role> and <user> tags, except for one <user> tag with a roles element to use as a template. Modify this <user> element to set a username and password for yourself, with roles of "manager,admin". Every time that Tomcat starts up, it will create any necessary <role> elements for you, so you don't need to add them.

server.xml
If you are running Tomcat 5.0.x, you can't use Java 1.5 features in Servlets. to enable Java 1.5 features, edit the shared file CATALINA_BASE/conf/web.xml and set the two init parameters compilerSourceVM and compilerSourceVM to the value 1.5. Tomcat 5.5.x fully supports Java 1.5 out of the box.

System Properties
You may want to set the environmental variables CATALINA_PID or CATALINA_OPTS in addition to CATALINA_HOME and JAVA_OPTS. The first specifies a location of where to store the pid file, and this is a must when running multiple instances on UNIX or Cygwin. (The UNIX init script included in the Starting a Tomcat Instance chapter sets this automatically). I don't know the implications of setting a PID file on Windows without Cygwin. CATALINA_OPTS is immensely useful for setting debug parameters, Java memory settings, etc. One very common use is to set the system property java.awt.headless to true. Most graphical ap19

Configuring Tomcat

plications (like Jasper, JFreechart, LiquidOffice, StyleReport, etc.) will halt Tomcat when they render if something isn't done to disable display rendering, and this is by far the easiest method. (This problem occurs with most J2EE servers, not just Tomcat). Here's how to make this setting in UNIX.

export CATALINA_OPTS: CATALINA_OPTS=-Djava.awt.headless=true BTW, JAVA_OPTS does the same thing as CATALINA_OPTS, but applications other than Tomcat use the variable JAVA_OPTS for this same purpose, so if you want a Java setting to apply only to Tomcat, use CATALINA_OPTS.

Final Setup
Start up Tomcat with the command %CATALINA_HOME%\catalina.bat start on Windows, or $CATALINA_HOME/catalina.sh start on UNIX. You must have the environmental variables CATALINA_HOME and CATALINA_BASE set, or the startup won't work right. Connect up to the home page and drill down to the Manager web app. Unless you specifically want to use Webdav or Tomcat clustering, undeploy the applications webdav, balancer, host-manager, Drill down to the Administration web app from the hom page to add more accounts, global J2EE datasources or mail servers, access logs, and IP address restrictions. Make sure to Commit changes that you make (although Committing is not necessary for user/role modifications), but don't expect your changes to become active until Tomcat is restarted. See the Tomcat Quirks chapter about Admin app quirks. See the Tomcat-Bundled Web Apps chapter about the Tomcat administrative web apps, and the Securing Tomcat's Administrative Web Apps chapter about how to secure them. CATALINA_BASE/logs will contain the Tomcat logs for this instance. Shut down Tomcat with the command %CATALINA_HOME%\catalina.bat stop on Windows, or $CATALINA_HOME/catalina.sh stop on UNIX.

J2EE Resources
If you are not using J2EE/JNDI to obtain your resources, then ignore this section because your resources are handled entirely by your application. This would be the case if your web app is coded like a standalone app (w.r.t. obtaining resources), or if you use Spring (without JNDI lookups). The remainder of this chapter assumes that you want to use J2EE or JNDI resources. With Tomcat, one can define all resources at the application level. I explain the more common J2EE idiom where objects are defined at the global level and these global resources are allocated to the applications. The basic strategy to use global resources in Tomcat is to define the global resources in CATALINA_BASE/config/server.xml, perhaps using the Tomcat Administration web app, then create application-specific JNDI links to these resources in your applications' <Context> elements of server.xml, or (usually better), in the application's context.xml file. The context.xml file is a Tomcat-specific descriptor which you bundle into your web app's META_INF directory. Tomcat will effectively add the contents of this file to your application's virtual server.xml <Context> element. When you deploy, Tomcat will copy your context.xml file to CATLINA_BASE/conf/Catalina/localhost/<APPNAME>.xml. It functions as a link between vendor-portable J2EE descriptors and Tomcat, in the same way that weblog.xml is the Weblogic-specific links vendor-portable J2EE descriptors to Weblogic.

20

Configuring Tomcat

Authentication user/role lists


I'll explain how to use the single Tomcat Memory Based Realm. This is great for development use, because you can use the single text user/role list for as many applications as you wish, and you can maintain the list with the Tomcat Administration web app or a text editor. You should obviously use https and protect the password file if your application is accessible to external users. Once you have the Memory Based Realm set up and working, it will much easier for you to understand and follow the instructions in the Tomcat docs for production quality realm implementations. The "User Definition" section of the nav panel of the Tomcat Administration panel can be used to graphically edit the file CATALINA_BASE/conf/tomcat-users.xml. Sometimes changes become active right away, but usually you will have to restart Tomcat.

Tip
If hand editing the tomcat-users.xml file, you don't need to add any <role> elements. When Tomcat starts up, it will automatically create a <role> elements for each role you reference in your <user> elements.

Data Sources
The Admin web app works well to define global J2EE data sources. Tomcat will wrap your data sources with dbcp connection pooling unless you override with custom configuration. Applications should be able to access data sources with global JNDI names, but I've never been able to get that to work with Tomcat. Using app-specific resource-refs to the global data sources works fine, however.

Logging
Tomcat logs to files in CATALINA_BASE/logs. stdout and stderr from your running applications will find their way into the file catalina.out. Servet.log() entries make it to the localhost log file. For application logs, you can use ${catalina.base} in your log4j config files, since tomcat sets this system property for out. This avoids multiple Tomcat instances from clobbering the same appender output files.

21

Chapter 6. Securing Tomcat's Administrative Web Apps


Recommended Setups
This chapter is not about Tomcat security in general. It is a HOWTO guide for securing the administration web apps in a simple and efficient way which works well whether or not you also need to secure end-user access to any portion of your web apps; and whether or not you use a httpd front end. If you are running local Tomcat instance(s) on a personal worksation, and you are assured that nobody else can "get onto" your PC, then the easiest solution by far is to just limit access to the administrative applications to the localhost address. To do this, use the Administrative Application. Drill down to Tomcat Server / Service Host and create a RemoteAddrValve to both Context (/admin) and Context (/manager). Restrict remote addresses to 127.0.0.1. Save and commit. The remainder of this chapter explains how to require direct Tomcat SSL encryption to just the Tomcat administrative web apps. If you have a httpd front end, the front end can just ignore the administrative web apps. This has the added benefit of avoiding ambiguity and considerable possible points-of-failure when just trying to administer your Tomcat server. Regardless of whether you use distributed httpd front ends, load balancers, etc., if you use URL https://saturn.myco.com:8443, you know that you are administering Tomcat on host "saturn". There is no effect to traffic not involved with teh administrative web apps. Note that this is not the way that SSL encryption is done for normal web apps, where the pipe is encrypted only between the web browser and the httpd front end (although you would have to use a Tomcat SSL plugin Connector if you used httpd front end(s) on remote servers separated by a nontrusted network).

Procedure 6.1. Securing Admin Apps with SSL plus IP Filters


1. First, create a self-signed certificate using keytool. There are simple examples at http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/keytool.html. There's no reason to purchase a commercial certificate. Each time that you access the web apps with a new web browser, you just need to view the certificate details to verify that it is the cert that you created. You accept the cert "forever" and that browser won't bother you about it again. (Well, unless your browser looses its saved certification settings, or the certificate expires... for this reason, set the certificate lifetime years in the future). Add a SSL listener to Tomcat by adding another <Connector> element right beneather your main <Connector> element.

2.

Example 6.1. SSL Connector Element


<Connector port="5003" maxHttpHeaderSize="8192" keystoreFile='conf/tcdirect.store' keystorePass='xyzabc123' keyAlias='tcdirect' scheme="https" secure="true"/> You obviously need to specfiy a port number which is available. The keystoreFile is a path to the key* attributes refer to the key store which you created in the previous step. You also need to add a redirectPort attribute to your original (non-SSL) <Connector> element, with value being the 22

Securing Tomcat's Administrative Web Apps

new SSL port number. This tells Tomcat to redirect to our SSL port when encryption is required (as we will require in the next step). Make sure to read-protect this server.xml file for now on, since it now contains a password. 3. Edit the files CATALINA_HOME/server/webapps/admin/WEB-INF/web.xml and CATALINA_HOME/server/webapps/manager/WEB-INF/web.xml Right before the closing </security-constraint> tag, add the following <user-data-constraint> element.

Example 6.2. web.xml Element requiring SSL


<user-data-constraint> <transport-guarantee>CONFIDENTIAL<transport-guarantee> <user-data-constraint>

4.

Finally, use the Administrative web app itself to restrict access to the source IP addresses of the site administrators. Use the same exact method as described at the top of this page, except instead of restricting to 127.0.0.1, you will restrict to the source addresses for all of the Tomcat administrators. Narrow access as much as possible. If the site administrators have static IP addresses, then use that address list. If DHCP is in use, then find out what subnets the administrators' addresses will be allocated from and use those subnets. In the worse case, you can set the list to all of your company or ISP, which will still exclude most of the hacker population of the world. It could well be, however, that you can't narrow the source IPs any more than is already restricted by existing firewalls at your company. If so, just skip this step.

23

Chapter 7. Tomcat Deployer Client


When I get to it, this will document the Tomcat deployer client which allows you to deploy webapps to Tomcat over the network using Ant.

24

Chapter 8. Tomcat Quirks


Typical run-time failures
Whenever Tomcat fails, always check your application logfiles and the Tomcat log files at $CATALINA_BASE/logs. One easy-to-recognize kind of error which shows up in the Tomcat logs are out-of-memory errors. These may be due to the cumulative expenditures of memory due to bad deployments, etc., since your last Tomcat startup. In that case, just restart Tomcat (often, in this situation, you will need to kill the lead pid yourself, and sometimes all of the children pids). If the problem occurs after a clean restart and just running your apps normally, then your web apps require more RAM to run. In that case, set the environmental variable JAVA_OPTS (like to -Xmx512m to increase from the default of 64M to 512M). Where to set this env. variable depends on how you start Tomcat. If you use the Suse init script, you would set it in /etc/sysconfig/j2ee. If you use my init script, you can set the default for all Tomcat instances in the init script itself, or for specific Tomcat instances in $CATALINA_BASE/instance.env.

Deployment failures
The most annoying kind of deployment failures are partial failures. Tomcat is really stupid about items in the webapps directory which it doesn't think are webapps. It will entirely ignore them. If you are a remote user, you will have no idea that the item is even there. If there happens to be a remnant from a previous incomplete undeployment, or if a previous deployment with that name partially failed for you or somebody else, then it will be in the webapp directory but Tomcat won't see it. When you try to deploy a webapp with the same name, it will choke because it will try to create the file or directory when there is already one there with the same name. It will either not tell you there is any problem at all, or it will just say that the deployment failed. The fix is to manually remove the unrecognized file or directory from the webapps directory. If your webapps consume more than the max JVM RAM (which defaults to 64M), that sometimes looks like a deployment problem. Check the Tomcat logs and read the previous section. Another problem that can prevent webapps from starting is if your webapp requires a Graphics context. There are many third party libraries that require a graphics context, most notably JasperReports (and probably JFreeChart). I forget the exact error message that shows up in the logs (it is not intuitive). I'll add that here the next time I encouhter it. But the fix is just to add the JAVA_OPTS Djava.awt.headless=true. See the previous section about where to set JAVA_OPTS. (For ancient JVM's, you used to run graphics emulators like Xvfb. Luckily the headless option works better and is much easier to set up.). Tomcat on Windows has a terrible time releasing Jar files. Make sure that you are not "tailing", "moring", or otherwise accessing log files or anything else to do with a web app when you attept to stop or deploy it. What will frequently happen is that resources within the web app will get completely stuck and you won't be able to remove them. Attempting to remove them while Tomcat is still running can make things get so bad that even shutting down Tomcat won't help and you'll have to reboot. The problem with not being able to remove these files is that you can't redeploy the application.

Manager webapp Quirks


The Manager webapp does very inadequate validation of the names that you supply. If you accidentally paste a space along with a war file name, the deployment will fail with no error message anywhere near to close to indicating the real cause. Similarly with other naming problems. If you suspect this kind of problem, you really need to get on the server and see what is really in the webapps directory. 25

Tomcat Quirks

"Reload" does not re-read the web.xml file from applications. You must stop and start the web app to do that.

Administrative App Quirks


The Admin app realy has a crappy persistence implementation. Often you will say to commit, and you will get an error message. I've found that things work much better if you take your time and make sure that operations complete before doing something else (including Committing). Commits in the Admin web app often cause restarts of effected web apps, including the Admin app itself! After you hit Commit, just wait a couple minutes for the Commit to complete. It's likely that the Admin web app will have restarted and you will get an authorizatin failure when you try to do anything else. Just log back in again.

Manual deployment failures


If you do local deployments by copying or moving war files or webapp directory branches into the webapps directory, then you are susceptible to directory polling race condition problems... and you probably will encounter them. The solution is to use a Webapp Staging Directory.

Tomcat is stuck!
By stuck, I mean that the Tomcat processes are running, but you can't get it to do anything for any web app. (Sometimes you get empty pages back, but usually the server will accept requests but will not reply at all). This is an extremely common problem with Tomcat. I have never encountered any app server that will not sometimes get stuck when running bad applications, but Tomcat is pretty bad in this respect. Over many years of seeing this behavior, it seems to happen either (a) upon deploying a problematic web application (or at the next Tomcat startup after said deployment), or (b) when a webapp runs and throws exceptions (which you can see in the Tomcat log files). I have always been able to recover from these problems by completely clearing the problematic webapp(s) and re-deploying them, as described here. If you are running Tomcat 5.5.x, and it chronically gets stuck upon startup, then switch to Tomcat 5.0.x. By chronically, I mean, you follow the procedures below, but the problem keeps recurring. I know that this can happen with Tomcat 5.5.x and Java 1.4 with large or troublesome webapps. (With the Java 1.4 patch, of course). I don't know about the reliability of Tomcat 5.5.x with Java 1.5.

Note
This section assumes that you have previously set up a Webapp Staging Directory. The first recovery strategy is to restart Tomcat. There's about a 50% chance that Tomcat won't shut down properly. See the Tomcat won't shut down! section if that happens. If things are still stuck after a restart, you need to identify the problematic webapp. If Tomcat gets stuck immediately upon startup, then you can find the last webapp start Tomcat attempted to start up in the Tomcat logs. If Tomcat gets stuck when you actually hit a webapp, then that's the one. Shut down Tomcat completely again. Wipe out the work directory for the problematic webapp. The work directory resides at a location like $CATALINA_BASE/work/Catalina/<HOSTNAME>/<APPCONTEXTROOT>. If you deployed a war, wipe out the exploded directory branch $CATALINA_BASE/<APPCONTEXTROOT>. Move your deployed item (a war file, or a webapp directory) from $CATALINA_BASE/webapps/<APPCONTEXTROOT> to inside of your webapp stage directory $CATALINA_BASE/webapps/stage/<APPCONTEXTROOT>. 26

Tomcat Quirks

Start up Tomcat and verify that everything runs ok (besides the webapp which you have manually undeployed). If another webapp causes problems, repeat the procedure above for other problematic webapps. Once things are happy, manually redeploy the webapp by moving it back from the stage directory to the main webapps directory. I.e., from $CATALINA_BASE/webapps/stage/<APPCONTEXTROOT> to $CATALINA_BASE/webapps/<APPCONTEXTROOT>. Restart Tomcat. If things fail after you redeploy the webapp, then this webapp has serious internal problems which need to be fixed before it will run on Tomcat. There should be exception stack traces in the Tomcat web logs and/or clues in your application logs.

Tomcat won't shut down!


After you shut down Tomcat in any way, do a ps and see if there are remaining "java" processes owned by your Tomcat owner. If so then telnet to the SHUTDOWN port on localhost, type "shutdown" and hit ENTER. (The shutdown port is listed in the file $CATALINA_BASE/conf/server.xml. Check the processes again. You're on your own doing this in Windows. In UNIX, use ps (or a variant) to find the parent "java" process owned by your Tomcat owner. If you are starting Tomcat with an init script, the ppid of this process leader will be 1. Send the TERM signal (not KILL or INT or anything else) to this process. The processes should all quit in about a second. (Depending on your operating system, your JVM, and even your JVM settings, you may see one process per thread, or just one for each JVM).

Warning
LAST RESORT. If the TERM signal doesn't stop Tomcat, then send the KILL signal to the process leader. You want to avoid this because it doesn't give the threads a chance to gracefully shut down, but more importantly, because it's more likely that the process leader will not shut down the children. In that case, you will have to hunt down all of the children and kill them with TERM or KILL (the former if it works, otherwise the latter).

Email Config Problems


When sending SMTP email, somehow the Properties that you supply to the Session are ignored. To get around this, set Java sys properties (like mail.smtp.host) via $CATALINA_OPTS.

27