Installing Tomcat on Apache

Introduction

Overview

Installing Tomcat with WARP can be particularly challenging if what you are looking to do is substantially different than the simple example that is included in Tomcat's provided server.xml. In addition, at the time this document was created there was effectively no additional documentation. As such, this was put together to aid those looking to do more with their combined Tomcat, WARP and Apache system.

Before reading any further, here is what the document outlines:

  1. How to make WARP-based changes to Apache, though it is not an Apache manual.
  2. How to setup a multiple Tomcat instance installation.
  3. How to setup multiple virtual hosts.
  4. What configuration files should be modified or created, not how to build Tomcat from source.
  5. How to install using Tomcat for JDK 1.4, though the instructions, other than directory name changes, will work with the non-JDK 1.4 version.
  6. How to install on RedHat, though should assist other installs.
  7. Does not discuss how to install the JDK.
  8. Does not discuss how to setup Realms.
  9. Does not discuss how to deploy web applications into Tomcat.

Software Versions

The installation described in this document was successfully performed on and using the following versions of various pieces of software.

The Scenario

This documentation has outlines and contains samples for the following situation.

There are three virtual hosts, www.domain.com, intranet.domain.com and extranet.domain.com, that will be be serving JSP's from from the root/home directory (e.g. http://www.domain.com/index.jsp).

intranet.domain.com and extranet.domain.com have both SSL and non-SSL sites. The non-SSL sites primarily exist to let people know they should use the secured site.

There will be two Tomcat instances. One instance is just for www.domain.com. The other instance will run the SSL and non-SSL intranet.domain.com and extranet.domain.com sites. In addition to providing a good example of multi-instance Tomcat, it means that a serious error in one VM will not take down the other.

Finally, there is actually only one IP address to share between all virtual hosts.

Preparing Tomcat

Installing Tomcat

Tomcat is available as source, a file archive (tar/zip) or as an RPM. With the requirement to have multiple instances, the RPM is not suggested. It is more for someone looking to install a single instance.

For those that are curious though, the RPM install does the following:

  • places executable jars/scripts in /usr/bin
  • places the instance configuration information in /var/tomcat4
  • places a tomcat configuration file in /etc/tomcat4
  • places a start script into /etc/init.d
  • creates a user tomcat4 for running tomcat under

The install described here is more traditional. In /usr/local/packages create a directory called tomcat. Download the necessary tar file into the tomcat directory and untar it. This should create a directory /usr/local/packages/tomcat/jakarta-tomcat-4.0.3-LE-jdk14.

To make management easier, particularly when you look to upgrade Tomcat in the future, in the /usr/local/packages/tomcat directory create a symbolic link, called latest, to the jakarta-tomcat-4.0.3-LE-jdk14 directory. This is accomplished with the following command.

ln -s jakarta-tomcat-4.0.3-LE-jdk14 latest

NOTE: If you are using the complete release of Tomcat, the directory names will be slightly different. Please change as appropriate.

Now it is important to understand two environment variables that Tomcat uses.

$CATALINA_HOME This environment variable indicates the location of the root Tomcat install directory. This is where Tomcat can find the main scripts, system jar files, etc. As outlined in this document, the value should be /usr/local/packages/tomcat/latest.
$CATALINA_BASE When running multiple instances of Tomcat this variable indicates where the root location of one of the instances. This is so Tomcat can find instance configuration information, temporary file locations, etc. When you have a single instance of Tomcat it is typically the same as $CATALINA_HOME.
NOTE: Don't worry about setting these environment variables yet. Scripts will be created to do just that.

Installing Instances

The installation described here is for two Tomcat instances, so you need to set up two $CATALINA_BASEs. This installation uses the following directories, which you will need to create.

/web/corporate This is the location of the www site.
/web/private This is the location of the intranet and extranet sites.

Tomcat requires the following set of directories underneath each $CATALINA_BASE.

conf The location of the configuration files, such as server.xml.
logs The location of the instance's log files.
temp A directory typically used for temporary data.
webapps The location of the web applications and sites served up by this Tomcat instance.
work The temporary directory used by Tomcat for doing things like compiling JSPs, etc.

All of these directories, except for temp, are already located in the $CATALINA_HOME directory. Create the temp directory and then copy the conf, logs, webapps and work directories from /usr/local/packages/tomcat/latest into both /web/corporate and /web/private.

Securing the Installation

NOTE: This section only briefly touches upon security issues that may arise with a dynamic web server like Tomcat. It is here to provide a couple common sense set up guidelines. Describing a more secure installation is outside the scope of this document.

First, a user should be created. Whenever possible, server applications should run as something other than root. This minimizes the chance of an exploit in the server application giving up root access to the server. As such, a user called tomcat whose home directory is $CATALINA_HOME (/usr/local/packages/tomcat/latest tomcat) should be created using the following command.

useradd -d /usr/local/packages/tomcat/latest tomcat

With the user created, it is imperative that the account has appropriate access to the directories it will use. Both ownership and permissions are set.

For the $CATALINA_HOME directory, the following is needed.

chown -R root:tomcat /usr/local/packages/tomcat/latest/logs
chown -R root:tomcat /usr/local/packages/tomcat/latest/webapps
chown -R root:tomcat /usr/local/packages/tomcat/latest/work

chmod -R ug=rwX, o=rX /usr/local/packages/tomcat/latest/logs
chmod -R ug=rwX, o=rX /usr/local/packages/tomcat/latest/work
chmod -R u=rwX, go=rX /usr/local/packages/tomcat/latest/webapps

NOTE: Notice the webapps permissions are slightly different. The explanation for this is below.

For each $CATALINA_BASE directory (/web/corporate and /web/private), the following is necessary.

chown -R root:tomcat /web/corporate

chmod -R u=rwX, go=rX /web/corporate
chmod -R g+w /web/corporate/logs
chmod -R g+w /web/corporate/temp
chmod -R g+w /web/corporate/work

chown -R root:tomcat /web/private

chmod -R u=rwX, go=rX /web/private
chmod -R g+w /web/private/logs
chmod -R g+w /web/private/temp
chmod -R g+w /web/private/work

The above ownership and permission settings made a few assumptions. First, Tomcat needs to be able to write into the log, work and temp directories. This is because it creates files and appends to logs. Second, Tomcat is NOT allowed to write to into the webapps directory. Unless you absolutely believe you need write access, do not allow it. This otherwise allows would-be hackers to more easily change your web site and/or add code of their own should an exploit be found. Always try to think with a security conscious mind.

NOTE: Not allowing the Tomcat user to write into the webapps directory will have one effect on the installation. In the server.xml files, found later in the article, the Host tag has a unpackWARs attribute to indicate whether Tomcat is to unpack WAR files. If you would like to have Tomcat unpack WAR files you must give Tomcat write privileges to the webapps directories. For security reasons, this is not recommended. Though, interestingly, Tomcat does need write access to the work directory so it can compile .jsp files. This, of course, makes the resulting .jsp class files more vulnerable.

Execution Scripts

Tomcat is now in place, but scripts are necessary to get it going. The scripts provided below are not the most ingenious, but get the job done. They should be placed into the directory /usr/local/packages/tomcat/latest/scripts. This directory will need to be created.

The scripts were designed with the following in mind:

  • To be called both from the command line and during OS initialization and shutdown.
  • To set the appropriate environment variables.
  • To start the processes running as the user tomcat.

The following two scripts are for starting the two Tomcat instances.

This first script is called corporate.

#!/bin/sh

# set the environment

CATALINA_BASE=/web/corporate
CATALINA_HOME=/usr/local/packages/tomcat/latest
JAVA_HOME=/usr/java/latest
JAVA_OPTS=-server

export CATALINA_BASE CATALINE_HOME JAVA_HOME JAVA_OPTS

exec "$CATALINA_HOME"/bin/catalina.sh "$@"

The second script, called private, looks like the following:

#!/bin/sh

# set the environment

CATALINA_BASE=/web/private
CATALINA_HOME=/usr/local/packages/tomcat/latest
JAVA_HOME=/usr/java/latest
JAVA_OPTS=-server

export CATALINA_BASE CATALINE_HOME JAVA_HOME JAVA_OPTS

exec "$CATALINA_HOME"/bin/catalina.sh "$@"

These scripts set up the environment for the Tomcat instances. The JAVA_HOME value is the location of your Java VM and JAVA_OPTS contains options that are sent to Java upon starting Tomcat. The -server being passed in JAVA_OPTS tells the Java to use the server virtual machine; this is recommended since, as the name suggests, the VM is tuned for running in a server environment. These environment variables are used by Tomcat's catalina.sh script.

NOTE: Other than the -server option for JAVA_OPTS, there are other options you may want to consider depending on your applications or sites. For example, -Xmx<size> sets the maximum amount of memory for Java to use (e.g. -Xmx128m sets the maximum memory usage to 128 megabytes). For more options, type java -X on the command line or visit Sun's Linux Java Tool Description.

The two scripts take parameters, which are passed to the catalina.sh script. The parameters are used to control the instance. Common parameters include start (for starting the instance) and stop (for stopping the instance). If parameters are not provided then catalina.sh will list the options.

The above scripts did not start Tomcat using the correct user account. The following script, called server.sh, is designed to do just that.

#!/bin/sh

# control the script of choice

echo "Attempting to [$2] on [$1]."
su - tomcat -c \
         "/usr/local/packages/tomcat/latest/scripts/$1 $2 $3"

The script simply takes the name of one of the previously described instance scripts and the parameters to start or stop and then executes it making sure to run under the appropriate user account. This is important because if you experiment and start the instance under the root account, Tomcat will create files with permissions preventing the tomcat account from accessing them.

The final script, called all_servers.sh, is designed to be called during OS initialization, or if you want to control both instances from the command line.

#!/bin/sh

# control all of the servers we are interested in

/usr/local/packages/tomcat/latest/scripts/server.sh \
         corporate $1 $2
/usr/local/packages/tomcat/latest/scripts/server.sh \
         private $1 $2

Configuring Apache

Apache Web App Module

Apache is being configured to use WARP. The first necessary item is getting the mod_webapp.so. Once downloaded, it should be placed in Apache's libexec directory.

Next, Apache's httpd.conf file must be modified.

At the start of the Apache httpd.conf file place the following lines. These lines should not be contained within any other directive.

# Load the module

LoadModule webapp_module libexec/mod_webapp.so
AddModule mod_webapp.c

# Setup the connections

WebAppConnection conn_corporate_http warp localhost:8006

WebAppConnection conn_private_http warp localhost:8011
WebAppConnection conn_private_https warp localhost:8012

In the first few lines, Apache is instructed to load the module and make it available for use within Apache.

Following that a set of connections are defined. These connections are what allow Apache to communicate with Tomcat using WARP.

The first connection is used by the corporate web site.

The second connection is used by the non-SSL intranet and extranet sites. In many cases sites like these are designed just to tell people to visit the secured version. Tomcat is probably a bit wasteful in this case, but it makes a great configuration example case.

Finally, the third connection is used for the SSL intranet and extranet sites. This does mean that the two virtual hosts will share a connection. This isn't a problem.

Since a single IP address is being shared for all of virtual hosts, the following lines are needed for Apache. This is not specifically a Tomcat configuration issue.

### Name Base Virtual Hosts

NameVirtualHost 192.168.120.90
NameVirtualHost 192.168.120.90:443

Even though it is a single IP Apache needs to know if name-based virtual hosting is to occur on both IPs and ports. When the port is not listed, Apache assumes port 80. So in the lines above, the first line is for standard http (on port 80) and the second is for https (SSL, on port 443).

Apache Non-SSL Virtual Hosts

With the connections and name-based virtual hosting in place, the non-SSL virtual hosts are defined.

#################################
# Corporate Web Site
#################################
<VirtualHost 192.168.120.90>
    ServerName www.domain.com
    DocumentRoot /web/corporate/webapps/www/http

    ServerAdmin webadmin@domain.com

    # Log Set-Up
    ErrorLog /httpd/logs/www_http_error_log
    CustomLog /httpd/logs/www_http_access_log combined
    
    # Tomcat connection (config is in tomcat)
    WebAppDeploy . conn_corporate_http /

    <Location /WEB-INF>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Location>

    <Directory /web/corporate/webapps/www/http>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Directory>
</VirtualHost>

There are a couple things to point out.

First, the WebAppDeploy setting has an application name of ".". This was done because Tomcat's server.xml file is actually used to control the web applications. More information is provided in the following virtual host sample.

Second, the DocumentRoot is set, but Apache never uses it. The directive is there as a form of documentation. The reason it is never used is because the WARP connection states that the root ("/" in the WebAppDeply statement) is to be sent to Tomcat. To make sure Apache does not serve from the DocumentRoot the Directory directive explicitly prohibits Apache from serving from that directory.

NOTE: When WARP is set to serve from the root of a virtual host, Apache actually "ignores" Directory directives . Location directives on the other hand are actually checked before sending them through WARP. So denying access to Location "/WEB-INF" is something that Apache will make sure happens. Yes it is redundant since the JSP/Servlet specification does not allow access to the special "/WEB-INF" directory. The statement is there to show how Apache and Tomcat behave through WARP.

The other non-SSL virtual hosts are as follows:

#################################
# Domain's Intranet Web Site
#################################
<VirtualHost 192.168.120.90>
    ServerName intranet.domain.com
    DocumentRoot /web/private/webapps/intranet/http

    ServerAdmin webadmin@domain.com

    # Log Set-Up
    ErrorLog /httpd/logs/intranet_http_error_log
    CustomLog /httpd/logs/intranet_http_access_log combined

    # Tomcat connection
    WebAppDeploy . conn_private_http /

    <Location /WEB-INF>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Location>

    <Directory /web/private/webapps/intranet/http>
        Options None
        AllowOverride None

        order deny,allow
        deny from all
    </Directory>
</VirtualHost>

#################################
# Domain's Extranet Web Site
#################################
<VirtualHost 192.168.120.90>
    ServerName extranet.domain.com
    DocumentRoot /web/private/webapps/extranet/http

    ServerAdmin webadmin@domain.com

    # Log Set-Up
    ErrorLog /httpd/logs/extranet_http_error_log
    CustomLog /httpd/logs/extranet_http_access_log combined

    # Tomcat connection
    WebAppDeploy . conn_private_http /

    <Location /WEB-INF>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Location>

    <Directory /web/private/webapps/extranet/http>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Directory>
</VirtualHost>

What may stand-out once again are the WebAppDeploy directives. They are set to use the exact same connection, and more oddly, the exact same application name, ".". This would seem to imply they are using the same application to serve up the content. This isn't true. Tomcat can handle virtual hosts through WARP. The goal was to have one location manage the intricate details of how to serve the Tomcat applications. Thus the server.xml holds the necessary configuration.

NOTE: One comment regarding the application name in the WebAppDeploy directive. It isn't actually a name at all, but a directory reference that is relative to the appBase configuration settings in your server.xml. The application name will accept full-paths. For example, if the application name was set to "/" instead of "." (i.e. WebAppDeploy . conn_private_http /), the file system root would actually be served! So be sure you specify relative paths and double check your settings.

Apache SSL Virtual Hosts

With the non-SSL hosts defined, the SSL virtual hosts are next. The sample does not show some SSL-based configuration options Apache may need, and the SSL configuration options shown may not be suitable for your environment. Just set up your SSL as if Tomcat was not involved. Then make the change to communicate over WARP using the WebAppDeploy statement.

#################################
# Domain Intranet Site
#################################
<VirtualHost 192.168.120.90:443>
    ServerName intranet.domain.com
    DocumentRoot /web/private/webapps/intranet/https

    ServerAdmin webadmin@domain.com

    # Log Set-Up
    ErrorLog /httpd/logs/intranet_https_error_log
    CustomLog /httpd/logs/intranet_https_access_log combined
    CustomLog /httpd/logs/intranet_ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    # SSL Information
    SSLEngine on

    # SSL Cipher Suite:
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

    # Server Certificate:
    SSLCertificateFile /httpd/conf/ssl.crt/server.crt

    # Server Private Key:
    SSLCertificateKeyFile /httpd/conf/ssl.key/server1.key

    # SSL Engine Options:
    <Files ~ "\.(shtml)$">
        SSLOptions +StdEnvVars
    </Files>

    # SSL Protocol Adjustments:
    SetEnvIf User-Agent ".*MSIE.*" \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0

    # Tomcat connection (config is in tomcat)
    WebAppDeploy . conn_private_https /

    # Require a login
    <Location / >
        AuthType Basic
        AuthName "Domain Intranet - Confidential"
        AuthuserFile /httpd/passwords/intranet_passwords
        Require valid-user
    </Location>

    <Location /WEB-INF>
        Options None
    AllowOverride None
        order deny,allow
        deny from all
    </Location>

    <Directory /web/private/webapps/intranet/https>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Directory>
</VirtualHost>

#################################
# Domain Extranet Site
#################################
<VirtualHost 192.168.120.90:443>
    ServerName extranet.domain.com
    DocumentRoot /web/private/webapps/extranet/https

    ServerAdmin webadmin@domain.com

    # Log Set-Up
    ErrorLog /httpd/logs/extranet_https_error_log
    CustomLog /httpd/logs/extranet_https_access_log combined
    CustomLog /httpd/logs/extranet_ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    # SSL Information
    SSLEngine on

    # SSL Cipher Suite:
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

    # Server Certificate:
    SSLCertificateFile /httpd/conf/ssl.crt/server.crt

    # Server Private Key:
    SSLCertificateKeyFile /httpd/conf/ssl.key/server1.key

    # SSL Engine Options:
    <Files ~ "\.(shtml)$">
        SSLOptions +StdEnvVars
    </Files>

    # SSL Protocol Adjustments:
    SetEnvIf User-Agent ".*MSIE.*" \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0

    # Tomcat connection (config is in tomcat)
    WebAppDeploy . conn_private_https /

    # Require a login
    <Location / >
        AuthType Basic
        AuthName "Domain Extranet - Confidential"
        AuthuserFile /httpd/passwords/extranet_passwords
        Require valid-user
    </Location>

    <Location /WEB-INF>
    Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Location>

    <Directory /web/private/webapps/extranet/https>
        Options None
        AllowOverride None
        order deny,allow
        deny from all
    </Directory>
</VirtualHost>

Once again the connection is shared between both virtual hosts, and appears as though they are going to show the same web application. Remember, this is actually managed in the server.xml file.

Other than the SSL configuration information, the other new items are the Location directives on the root. Defined within it are settings that require people to login and authenticate with Apache. This is NOT the same thing as Tomcat's Realms. It is here to show two things.

  1. Location's are evaluated and executed on before WebAppDeploy.
  2. The CGI environment variable REMOTE_USER passes properly along WARP to your JSP's and servlets, allowing you to decide between Realms, Apache or some other form of authentication.

Modifying the server.xml Files

WWW server.xml File

With Apache configured, Tomcat's server.xml files must be edited.

The first file shown is for the Tomcat instance responsible for displaying www.domain.com. This file is located at /web/corporate/conf/server.xml.

<!-- The Server JVM -->
<Server port="8005" shutdown="SHUTDOWN" debug="0">
    <!-- Define an Apache-Connector Service for unsecured-->
    <Service name="Domain-Corporate-HTTP">
        <!-- the connector for non-https traffic -->
        <Connector className = "org.apache.catalina.connector.warp.WarpConnector"
          port="8006"
          minProcessors="5"
          maxProcessors="50"
          scheme="http"
          secure="false"
          enableLookups="true"
          appBase="webapps"
          acceptCount="10"
          debug="0"/>

        <!-- The WarpEngine in action -->
        <Engine className = "org.apache.catalina.connector.warp.WarpEngine"
          name="Domain-Corporate-HTTP"
          debug="0">

            <Logger className = "org.apache.catalina.logger.FileLogger"
              prefix="public_http_log."
              suffix=".txt"
              timestamp="true"/>

            <Realm className = "org.apache.catalina.realm.MemoryRealm" />

            <!-- Define the virtual hosts in use -->
            <Host className = "org.apache.catalina.connector.warp.WarpHost"
              name="www.domain.com"
              debug="0"
              appBase="webapps/www"
              unpackWARs="false" >

                <Context path="" docBase="http" debug="0"/>

            </Host>

        </Engine>
    </Service>
</Server>

This is a fairly simple server.xml. The item that stands out is the use of a Host element in the Engine. There are plenty of examples of this when using the HTTP connector, but this actually works with WARP as well.

The Host tag is used to define a virtual host, in this case www.domain.com. For this Tomcat instance it actually doesn't provide too much since there is only one. What you do see is that the appBase attribute in the Host element is what is actually used for the appBase for the web site, not the appBase defined in the Connector. The Host's appBase is the location that the application name in the WebAppDeploy statement (in the httpd.conf) is relative to.

The Host also specifies the class (via the className attribute). WARP does have its own Host, which actually derives off the standard Tomcat Host.

Within in the Host, a Context is defined. This Context is used to define the root directory of the web site. In otherwords, this is where the static HTML, JSP's, etc, are served from. The directory in this case is http, which, when expanded out, is /web/corporate/webapps/www/http.

While a Logger is defined here, it is different than Apache's logging. This Logger is useful when looking to diagnose possible problems with JSP's, servlets, and Tomcat configuration. If you prefer to use Tomcat instead of Apache for hit logs then you need to setup what is called a Valve. Please refer to the Tomcat documentation.

NOTE: There is one caveat when using Apache for hit logs while Tomcat is used. It is common practice to set, in a web application's web.xml, how to handle errors such as a 404, by specifying a page to return to the user. Doing this, however, means the request appears to Apache as a valid page access and not a 404. It is unclear if this behaviour is a bug. However, if you do not put error handling in the web.xml then you get the standard Tomcat Status 404 error page and the 404 is returned properly to Apache.
NOTE: When a Tomcat instance starts up, the catalina.sh script is set to dump standard error and standard out into the file $CATALINA_BASE/logs/catalina.out. It may also be a source of information if you are having trouble with your web applications or server.
NOTE: To verify a clean install, make sure the port defined in the Connector matches the WebAppConnection port in Apache's httpd.conf.

Private server.xml File

Finally, below is the intranet and extranet /web/private/conf/server.xml file.


<!-- The Server JVM -->
<Server port="8010" shutdown="SHUTDOWN" debug="0">
    <!-- Define an Apache-Connector Service for unsecured-->
    <Service name="Domain-Private-HTTP">
        <!-- the connector for non-https traffic -->
        <Connector className = "org.apache.catalina.connector.warp.WarpConnector"
          port="8011"
          minProcessors="2"
          maxProcessors="10"
          scheme="http"
          secure="false"
          enableLookups="true"
          appBase="webapps"
          acceptCount="10"
          debug="0"/>

        <!-- The WarpEngine in action -->
        <Engine className = "org.apache.catalina.connector.warp.WarpEngine"
          name="Domain-Private-HTTP"
          debug="0">

        <Logger className = "org.apache.catalina.logger.FileLogger"
          prefix="private_http_log."
          suffix=".txt"
          timestamp="true"/>

            <Realm className = "org.apache.catalina.realm.MemoryRealm" />

            <!-- Define the virtual hosts in use -->
            <Host className = "org.apache.catalina.connector.warp.WarpHost"
              name="intranet.domain.com"
              debug="0"
              appBase="webapps/intranet"
              unpackWARs="false" >

                <Context path="" docBase="http" debug="0"/>

            </Host>

            <Host className = "org.apache.catalina.connector.warp.WarpHost"
              name="extranet.domain.com"
              debug="0"
              appBase="webapps/extranet"
              unpackWARs="false" >
                <Context path="" docBase="http" debug="0"/>
            </Host>

        </Engine>
    </Service>

    <!-- Define an Apache-Connector Service for secured -->
    <Service name="Domain-Private-HTTPS">
        <!-- the connector for https traffic -->
        <Connector className = "org.apache.catalina.connector.warp.WarpConnector"
          port="8012"
          minProcessors="5"
          maxProcessors="20"
          scheme="https"
          secure="true"
          enableLookups="true"
          appBase="webapps"
          acceptCount="10"
          debug="0"/>

        <!-- The WarpEngine in action -->
        <Engine className = "org.apache.catalina.connector.warp.WarpEngine"
          name="Domain-Private-HTTPS"
          debug="0">

            <Logger className = "org.apache.catalina.logger.FileLogger"
              prefix="private_https_log."
              suffix=".txt"
              timestamp="true"/>

            <Realm className = "org.apache.catalina.realm.MemoryRealm" />

            <!-- Define the virtual hosts in use -->
            <Host className = "org.apache.catalina.connector.warp.WarpHost"
              name="intranet.domain.com"
              debug="0"
              appBase="webapps/intranet"
              unpackWARs="false" >

                <Context path="" docBase="https" debug="0"/>

            </Host>

            <Host className = "org.apache.catalina.connector.warp.WarpHost"
              name="extranet.domain.com"
              debug="0"
              appBase="webapps/extranet"
              unpackWARs="false" >

                <Context path="" docBase="https" debug="0"/>

            </Host>
        </Engine>
    </Service>
</Server>

This configuration has two Service elements. There is a reason for this. Only one Engine element is permissible per Service. It is within the Engine that you define your virtual Hosts. Since different content is served up on the same host name, but dependent upon whether the browser came in via SSL or not, two different Service areas are necessary.

NOTE:

The above example is appropriate in situations as described, where you are have an insecure intranet/extranet entry screen that simply redirects the user to the secured site. If, however, you are setting up an online store and want to carry session information between the insecure and secure location, you need to do things differently.

First, you can use just one Service element and place the secure and insecure Connector elements within it. The Engine is therefore shared and session information is shared.

Second, you need to make sure you use different host names for the name attribute in the two Host elements. For example www.store.com and secure.store.com. This will make it so you can easily serve up different content.

The first Service element is for standard HTTP. It is almost identical to the previous server.xml Service element, except the Engine has two Host elements. These Host elements represent the two virtual hosts, intranet.domain.com and extranet.domain.com. Within the Host elements are the directories that service as the appBase and, through the Context element, the root for the site.

The second Service element is for HTTPS. You can easily confirm this by comparing the Service's Connector element; the port in the Connector corresponds to the port of the connection defined in the Apache configuration file and used within the SSL-based VirtualHost.

There are three distinct differences between the first and second Service elements.

  1. The Connectors are using different ports.
  2. The Connector for HTTPS-derived communication has the attribute scheme set to "https", and secure set to "true". This doesn't mean the Connector is performing the encryption. Remember, Apache is doing all of the SSL handling. These attributes allow request.getScheme() and request.isSecure() calls in JSP or servlets to return "https" and true respectively.
  3. While the Host's in the SSL and non-SSL versions use the same appBase, the root Contexts are setup differently to reflect the different content that should be served.
NOTE: Once again, check your ports, but in addition, make sure they are different ports than what is used in the previous server.xml, otherwise it won't start properly. In fact Tomcat will silently fail on the command line.

Conclusion

Turning it On

At this point everything should now be set up to have a multi-instance Tomcat Installation that supports both SSL and non-SSL sites. To get it all started, just run the following:

/httpd/bin/apachectrl stop
/usr/local/packages/tomcat/latest/scripts/all_servers.sh start
/httpd/bin/apachectrl startssl

Assuming your Apache web server is in /httpd, everything should be operational!

 

If you have any questions or comments regarding this article, please do not hesitate to e-mail comments@codesta.com!

Reference Material

The Directory Structure

The following is a break-down of the main directories assumed and used by the example installation.

Apache Directories
 
/httpd
     The location of Apache.
/httpd/conf
  The location of Apache's configuration files, namely httpd.conf.
/httpd/libexec
  The location to place the mod_webapps.so so Apache can communicate with Tomcat.
 
Java Directories
 
/usr/java/latest
  The location of the java installation. The java executable should be in /usr/java/latest/bin.
 
Tomcat Installation Directories
 
/usr/local/packages/tomcat/jakarta-tomcat-4.0.3-LE-jdk14
  The location Tomcat was actually installed into.
/usr/local/packages/tomcat/latest
  Represents $CATALINA_HOME. It is a symbolic link to the location Tomcat was installed into.
/usr/local/packages/tomcat/latest/scripts
  The location of the execution scripts created to start/stop the Tomcat instances.
 
Tomcat Corporate Instance Directories
 
/web/corporate
  The $CATALINA_BASE for the corporate Tomcat instance responsible for the www.domain.com site.
/web/corporate/conf
  The location of the server.xml for the corporate Tomcat instance.
/web/corporate/webapps
  The root location of the web applications for the corporate Tomcat instance.
/web/corporate/webapps/www
  The root location of the web applications for the www.domain.com virtual host.
/web/corporate/webapps/www/http
  The root directory of the www.domain.com web site. This is where the site's main HTML and JSP's are served from.
 
Tomcat Private Instance Directories
 
/web/private
  The $CATALINA_BASE for the private Tomcat instance responsible for the intranet.domain.com and extranet.domain.com sites.
/web/private/conf
  The location of the server.xml for the private Tomcat instance.
/web/private/webapps
  The root location of the web applications for the private Tomcat instance.
/web/private/webapps/extranet
  The root location of the web applications for the extranet.domain.com virtual host.
/web/private/webapps/extranet/http
  The root directory of the extranet.domain.com web site. This is where the site's main HTML and JSP's are served from.
/web/private/webapps/intranet
  The root location of the web applications for the intranet.domain.com virtual host.
/web/private/webapps/intranet/http
  The root directory of the intranet.domain.com web site. This is where the site's main HTML and JSP's are served from.