I have done alot of work with Apache 1.3/Tomcat 4.1.X setting up virtual hosting
in a web hosting environment.  Please see my attached document.

Regards,

Glenn

Hans Kaiser wrote:
> Hi,
> 
> nobody knows how to solve it, or is it too simple for an answer?
> 
> best regards,
> Hans
> 
> 
>>Hello all!
>>
>>Is this list a closed one? I tried to post a message to the list, without
>>being subscribed, but that failed (I think so, I couldnīt see the mail on
>>the
>>archives)
>>
>>I will go on directly to my problems:
>>I am running an Apache 1.3.x and I have all my virtual hosts under
>>/home/web/host[anyhostnaming]
>>Now I need a servlet and a JSP Engine, therefore I want to use the Tomcat
>>4.x. But my users should be able to define their own contexts for the
>>tomcat.
>>So my questions are:
>>- how to configure the apache and tomcat to forward all JSP and servlet
>>request from apache to tomcat.
>>- how should I setup tomcat to make it possible, that only a defined list
>>of
>>users are able to use jsp/servlet?
>>- how to setup tomcat or must I setup the apache (if forwarding the
>>servlet/jsp request from apache to tomcat), that users are able to define
>>their own
>>contexts? Is it a security problem? I thought about something like a
>>distributed web.xml in a defined location in the users home dirs.
>>- Is it possible to limit the maximum used resources (load, memory ....)
>>of
>>tomcat?  Or even better per user basis?
>>
>>many thanks,
>>and best regards,
>>Hans
>>
>>-- 
>>GMX - Die Kommunikationsplattform im Internet.
>>http://www.gmx.net
>>
>>
>>--
>>To unsubscribe, e-mail:  
>><mailto:[EMAIL PROTECTED]>
>>For additional commands, e-mail:
>><mailto:[EMAIL PROTECTED]>
>>
> 


                Web Hosting with Tomcat 4 and Apache

Overview
========

There are a number of configuration issues and security concerns
which must be addressed when setting up Apache and Tomcat 4 for
virtual hosting of customer sites in a web hosting environment.

The major conerns are:

1.  Delegating to untrusted customers maintenance of their applications
    without compromising server security.

2.  Configuring Apache and Tomcat for virtual hosting.

3.  Surviving poorly written web applications installed by
    customers.  This includes fault tolerance and identifying
    which customer's web application is causing problems.

4.  Mimimize the amount of hand holding or config changes the
    apache and tomcat system administrators have to make.

This is written based on my experiences setting up this type
of hosting environment on Sun Solaris hardware.  Some of this
will be specific to Solaris, but in general should work for
almost any flavor of Unix.

Unix accounts and groups
========================

The user "tomcat" was created for running tomcat, it should
be created similar to the "nobody" account used for running
Apache.  The tomcat user is assigned to the group tomcat.
The tomcat user is a member of group "user".

The group "tomcat" was created as the group the user "tomcat"
is assigned to.

The group "user" was created, this is the group customer
ftp accounts are assigned to.  The "tomcat" account is a
member of this group so that both customers and tomcat
can write files in directories assigned to group "user".

Each customer has their own ftp account which is in group
"user".

There is a "webmaster" administrator shell account.  This
account is for your virtual host administrator. The
webmaster account is assigned to group "user" and is also
a member of group "tomcat".

Directory layout
================

The layout of directories is designed to make it as easy as
possible for customers to maintain their own web space content
and applications.

Here is an example of how I do it:

The customer is assigned an FTP account which has permission
to read their virtual host directory and write to a subset of
that.

For example, a customer may be assigned the following directory:

/export/home/www.customer.com root:other 755
--------------------------------------------

Within that directory are sub directories which the customer
can read and/or write. Listed are the directory names, 
ownership, and mode.

www webmaster:user 2775
----------------------

Apache document root directory.  Customer and tomcat can
both read/write directories and files.

logs root:other 755
-------------------

Directory where apache access_log and error_log are placed.
We also rotate these logs weekly and use bzip2 to compress
any log files older than 5 weeks.  Log files less than 5
weeks old are left uncompressed so that they can be used
by web statistic software like Analog. Customer can read
files in this directory but not write files.

tomcat tomcat:tomcat 755
------------------------

Directory used for the tomcat work and tomcat virtual host logs.
Only tomcat can write in this directory. Customer can read
files in this directory.

tomcat/work tomcat:tomcat 755
-----------------------------

Tomcat work directory for virtual host. Only tomcat can write
files.  Customer can read files. This allows customer to review
java source files generated during a JSP page compile.

tomcat/logs tomcat:tomcat 755 
------------------------------

Tomcat log directory for virtual host. Only tomcat can write
files.  Customer can read files. This allows the customer
to review their virtual host application logs.

reports webmaster:tomcat 2775
-----------------------------

Directory I use for placing custom reports generated for customer.
This is aliased into the customers document space and can password
restricted using a .htaccess file.

Apache VirtualHost config
=========================

We are using Apache 1.3.26.

mod_jk config
-------------

# Load Tomcat mod_jk 1.2
LoadModule jk_module          libexec/mod_jk.so
JkWorkersFile /usr/local/apache/conf/workers.properties
JkLogFile     /usr/local/apache/logs/mod_jk.log
JkLogLevel    error
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

I also use a script to rotate the mod_jk.log weekly.

VirtualHost config
------------------

<VirtualHost XXX.XXX.XXX.XXX:80>
ServerAdmin [EMAIL PROTECTED]
DocumentRoot /export/home/www.customer.com/www
ServerName www.customer.com

DirectoryIndex index.html index.htm index.shtml index.shtm index.jsp

# Alias the admin reports directory into webspace
# The files are located outside of webspace so that only files
# which the customer maintains are in their document root.
# This prevents conflicts and problems with publishing tools.
Alias /reports/ /export/home/www.customer.com/reports/

# Put the virtual host appBase in their apache web space document root.
# This makes it easier for customers to manage a mix of static and
# dynamic content by making directory paths relative to the same
# directory.
# JkAutoAlias will allow apache to server static content from web
# applications. JkAutoAlias also prevents apache from serving any
# files located in a web applications /WEB-INF/ directory.
JkAutoAlias /export/home/www.customer.com/www
# Implement request logging including request latency.
# This can be handy for generating graphs for the customer
# which shows the request latency for various JSP/Servlet requests.
JkRequestLogFormat "%w %v \"%r\" %U %s %T"

# Pass all *.jsp requests to Tomcat
JkMount /*.jsp ajp13
# Pass all /servlet/* requests to Tomcat
JkMount /servlet/* ajp13
# Pass all /*.do Struts actions to Tomcat
JkMount /*.do ajp13
# Mount the manager application
JkMount /manager/* ajp13

# Put the apache logs in the virtual host logs directory
ErrorLog        /export/home/www.customer.com/logs/error_log
CustomLog       /export/home/www.customer.com/logs/access_log combined
</VirtualHost>

Tomcat 4.1.x config
===================

server.xml Host config
----------------------

<!--
     appBase is set to the apache document root for the customers website
     workDir is places in the tomcat/work subdirectory of the customers
             virtual host directory
     unpackWARS is set to true so customers can update single JSP pages in
                the unpacked web application without having to redeploy the
                web application.
     liveDeploy is set to false to reduce overhead and force customers to
                explicitely install new webapps. This is required because
                the apache document root and the appBase are the same.
                We don't want tomcat checking all the directories in the
                customers document root every few minutes.
     deployXML is false, deploying an application runs with the permissions
               of catalina, setting this to true could compromise the security
               of your server.
     -->

<Host name="www.customer.com" debug="0"
      appBase="/export/home/www.customer.com/www"
      workDir="/export/home/www.customer.com/tomcat/work"
      unpackWARs="true" autoDeploy="true" liveDeploy="false" deployXML="false">

  <!-- A seperate realm is needed for each customer for the manager
       We configure our MySQL database privileges so that the customer
       can administer the users and roles for their realm.
       -->
  <Realm  className="org.apache.catalina.realm.JDBCRealm" debug="0"
          driverName="org.gjt.mm.mysql.Driver"
          
connectionURL="jdbc:mysql://localhost/www_customer_com_realm?autoReconnect=true"
          connectionName="customer" connectionPassword="password"
          userTable="users" userNameCol="user_name" userCredCol="user_pass"
          userRoleTable="user_roles" roleNameCol="role_name" digest="MD5" />

  <!-- Put their tomcat context log where customer can view them -->
  <Logger className="org.apache.catalina.logger.FileLogger"
          directory="/export/home/www.customer.com/tomcat/logs"
          prefix="tomcat_log-" suffix=".txt"
          timestamp="true"/>

  <!-- Several JNDI resources are setup for customer so that their
       web applications are more portable between their development
       environment and the production tomcat.
       -->
  <DefaultContext debug="0" reloadable="false">
    <!-- JNDI named resource for sending email -->
    <Resource name="mail/send" auth="CONTAINER"
              type="javax.mail.internet.MimePartDataSource"/>
    <ResourceParams name="mail/send">
      <parameter><name>factory</name>
        <value>org.apache.naming.factory.SendMailFactory</value>
      </parameter>
      <parameter><name>mail.smtp.host</name>
        <value>localhost</value>
      </parameter>
      <parameter><name>mail.smtp.user</name>
        <value>customer</value>
      </parameter>
      <parameter><name>mail.from</name>
        <value>[EMAIL PROTECTED]</value>
      </parameter>
    </ResourceParams>

    <!-- JNDI JDBC DataSource Resource for using MySQL dB.
         Each customer is provided with their own db for use
         in their web applications.
         -->
    <Resource name="jdbc/data" auth="CONTAINER"
              type="javax.sql.DataSource"/>
    <ResourceParams name="jdbc/data">
      <parameter>
        <name>factory</name>
        <value>org.apache.naming.factory.DbcpDataSourceFactory</value>
      </parameter>
      <parameter><name>user</name><value>customer</value></parameter>
      <parameter><name>password</name><value>password</value></parameter>
      <parameter>
        <name>driverClassName</name>
        <value>org.gjt.mm.mysql.Driver</value></parameter>
      <parameter>
        <name>driverName</name>
        <value>jdbc:mysql://localhost/customer_data?autoReconnect=true</value>
      </parameter>
      <parameter>
        <name>maxIdle</name>
        <value>50</value>
      </parameter>
      <parameter>
        <name>maxActive</name>
        <value>200</value>
      </parameter>
      <!-- maxWait needs to be long enough to survive JVM freezes during GC -->
      <parameter>
        <name>maxWait</name>
        <value>10000</value>
      </parameter>
      <!-- Removing abandoned db connections is critical for reliability  -->
      <parameter>
        <name>logAbandoned</name>
        <value>true</value>
      </parameter>
      <parameter>
        <name>removeAbandoned</name>
        <value>true</value>
      </parameter>
      <parameter>
        <name>removeAbandonedTimeout</name>
        <value>300</value>
      </parameter>
    </ResourceParams>
  </DefaultContext>

  <!-- Configure the manager for the customer, allowing the customer to
       deploy context.xml files is a security risk.
       -->
  <Context path="/manager"
           docBase="/usr/local/tomcat/server/webapps/manager"
           debug="0" privileged="true">
  </Context>

</Host>

Jasper Compiler
---------------

There are several problems with using javac from the JVM for JSP page
compilation.  First, there is a known memory leak.  Second, javac creates
alot of objects during compilation.  Using an external page compiler like
jikes reduces the memory footprint of tomcat and removes all the extra
GC overhead for cleaning up after javac.

Grab the source for jikes, compile and install it.

Edit $CATALINA_HOME/bin/catalina.sh and add $JAVA_HOME/jre/lib/rt.jar
to the CLASSPATH.

CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/bootstrap.jar:$JAVA_HOME/jre/lib/rt.jar

Edit $CATALINA_HOME/conf/web.xml to enable use of jikes as the JSP page compiler.

    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <!-- Uncomment to use jikes for JSP page compiles -->
        <init-param>
            <param-name>jspCompilerPlugin</param-name>
            <param-value>org.apache.jasper.compiler.JikesJavaCompiler</param-value>
        </init-param>
        <init-param>
            <param-name>jspCompilerPath</param-name>
            <param-value>/usr/local/bin/jikes</param-value>
        </init-param>
        <init-param>
            <param-name>logVerbosityLevel</param-name>
            <param-value>ERROR</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

Add the following shell environment variable to the start script
you use for Tomcat if you have JVM extensions installed.

$EXTDIRS=$JAVA_HOME/jre/lib/ext

server.xml Connector config
---------------------------

With mod_jk and Tomcat their is a 1 to 1 mapping of apache
httpd processes to AjpConnectors.  You must configure 
maxProcessors to a value greater than your apache MaxClients.

Set the minProccessors high enough so that there are enough
processors already created to handle your average load.
Tomcat doesn't start handling requests until they have all
been created.

Do not increase the acceptCount, if there is a long JVM freeze
due to GC, a large acceptCount can flood tomcat with requests.
This can have a cascading effect which can cause problems.

<Connector className="org.apache.ajp.tomcat4.Ajp13Connector"
           port="8009" minProcessors="50" maxProcessors="375"
           acceptCount="10" connectionTimeout="0" debug="0"/>


Tomcat JVM and server
---------------------

It is critical that the memory used by the JVM not be swapped
out to disk.  If portions of the JVM get swapped out to disk
the time it takes to do a full GC can be very long.  I have
seen 2-3 minutes.  And all this time tomcat is not handling
requests.  I recommend hosting tomcat on a server by itself
so that you can guarantee that the JVM stack does not get
swapped out to disk.

Run Tomcat using JVM 1.3.1 or greater.  Use the -server
startup option so that HotSpot server profiling and
optimization is used.

Knowledge of how to configure memory usage and GC for the
JVM is critical.  Your JVM settings can significantly
impact the performance of Tomcat.

At a minimum I recommend using incremental GC -Xincgc and
verbose logging of GC -verbose:gc so that you have data
for making decisions on how to adjust your jvm settings
for memory usage.

Here is an example of my JVM options for tomcat running
on a Sun 250 with 256MB of ram.

CATALINA_OPTS="-server -verbose:gc -Xms160m -Xmx160m -Xss128k -Xincgc 
-XX:+UseLWPSynchronization"

Ideally you don't want GC to ever take more than 10 seconds.

I am hosting all customers in the same instance of Tomcat,
but that is only a few customers at this time.  Based on
experience you may want to use multiple instances of Tomcat.
Or even one instance for each customer if you can afford to
dedicate those resources.

Tomcat Version
==============

I recommend using the latest Tomcat 4.1.X, it has some features
which I have added to make virtual hosting easier which are not
available in Tomcat 4.0.X.

Tomcat Security
===============

If you have untrusted users deploying web applications or modifying
JSP pages you must run Tomcat with the SecurityManager.  Your
catalina.policy configuration for customer web applications must
be strict enough to protect the security of your server and protect
one customer from another customer.  Yet by default grant enough
permissions so that you don't have to constantly change catalina.policy.

At this time you can not delegate to customers setting the security policy.
But when a web application is started the catalina.policy is reloaded.
So if you need to adjust the permissions for a specific customer's
web application you can modify catalina.policy and then do a reload
of the web applicaiton.

I am working on changes to the SecurityManager implementation in tomcat
which will safely allow delegation to customers administration of
their own security policy without compromising the server.  I am about
50% done with this but haven't been able to work on it for several weeks
due to vacation and other higher priorities.  I should be able to get
back to it in another week, and hope to have it done and committed to
CVS by the first week in August.

Tomcat runtime monitoring
=========================

There isn't much you can do to automatically monitor tomcat except
make sure it is handling requests.

I will be evaluating Introscope from Wily Technology next week to
see how well it can be used to do runtime monitoring and notification
of problems for Tomcat 4.

Gotchas
=======

There are still some issues using Tomcat that still need to be addressed.

1.  A way to automatically terminate a runaway request so that a poorly
    written customer applicaiton doesn't bring down tomcat.

2.  Pooling of mod_jk <-> AjpConnector sockets to remove the 1 to 1 mapping.

3.  manager stop/start/reload wierdness.  I have seen a few times when a
    customer did a stop/start or reload of a web application cause problems.

Summary
=======

I think this captures all the issues I encountered when setting
up apache and tomcat for virtual hosting of customers in a web
hosting environment.  I may have missed a few things.

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to