Perhaps you can gain some insight into this from the attached file. rls
"Curt LeCaptain" <[EMAIL PROTECTED]> 10/25/2002 07:49 AM Please respond to "Tomcat Users List" To: "Tomcat Users List" <[EMAIL PROTECTED]> cc: Subject: Virtual Hosts Okay... so, I've redone my complete Tomcat/Apache setup according to instructions on John Turner's website: http://www.johnturner.com/howto/apache1-tomcat404-howto.html Everything works as it should! :) Now... I'm completely baffled as to how to set up a virtual host in server.xml, I'm not exactly sure how to setup the elements and such to get directories to work. IE, I want a virtual host called "dev.infinity-tech.com" within there, where JSP's can be launched from the document root of that site (/www/docs/dev.infinity-tech.com) and servlets can be launched from a folder within that directory. If someone could help me out, or point me in a direction to figure this out, please, let me know! :) Curt LeCaptain -- To unsubscribe, e-mail: <mailto:tomcat-user-unsubscribe@;jakarta.apache.org> For additional commands, e-mail: <mailto:tomcat-user-help@;jakarta.apache.org>
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:tomcat-user-unsubscribe@;jakarta.apache.org> For additional commands, e-mail: <mailto:tomcat-user-help@;jakarta.apache.org>