User Tools

Site Tools


java:installationunderlinux

Installation of Tomcat under Linux

Preface

These notes are about installing Tomcat in a production environment under apache. This notes were taken while I were installing such product in a machine on a DMZ, so security were my first concern in every step I took.

Said that, it is possible that the document has misunderstandings and errors. Nobody is perfect. Use it at your own risk.

The machine I am using is a Virtual Server with 32 bits and a SuSE 11.1 installed.

Things we need to install

You should have the JRE installed in your machine. You can download it from Oracle website.

Make sure that you have defined a environmen variable JRE_HOME that points to the location of the JRE. In other words, this command should work:

rluna@machine:~> ($JRE_HOME/bin/java -version)
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode)

Yes, the version of java is a bit outdated. I've used the version that the current version of linux provided through the package manager.

Create a tomcat user and a tomcat group

The idea is to create a “tomcat” user and a “tomcat” group, own all the files of tomcat with this user and run the service with this user: this prevent that, in case of god-knows-what, an attacker would gain root privileges easily.

useradd --create-home --user-group --system -g tomcat tomcat

The –system option is to specify that the user must be a system account.

The -g is to specify that the default group for this account must be tomcat instead users, as used to be. And finnaly the -m option is for creating a home directory. I prefer to create a home directory for this type of users, just for store there certain downloads or configuration files.

If you want to log in as the tomcat user

As you may know, if you want to login as the user tomcat all you have to do is to change the shell:

useradd -s /bin/bash tomcat

and, to return the user to the prior state, you only have to do the following:

useradd -s /bin/false tomcat

Ensure that the user has an umask of 0027 or less

This can be checked out entering as the tomcat user or checking the /etc directory. This is for not leaving open files to every other user in the system.

Creating the directory

I've choose /usr/local/share as the main directory. I've created a directory called apache-tomcat-7.0.22 -this is the version I am using- and a link to this named tomcat: the rest of the commands, or services will be refered to the /usr/local/share/tomcat dir. With this resource, it will be easy to upgrade tomcat simply by changing the link.

mkdir apache-tomcat-7.0.22
chown tomcat:tomcat apache-tomcat-7.0.22
chmod 750 apache-tomcat-7.0.22
ln -s apache-tomcat-7.0.22 tomcat

Copy the contents (beware with the permissions)

Copy all the contents into the new location (or uncompress them), and make sure that the permissions are assigned to tomcat:tomcat and are the proper.

cp /home/tomcat/tmp/apache-tomcat-7.0.22/* . -R
chown tomcat:tomcat * -R

Do a basic cleanup

I've seen that the Windows .bat files are in the /bin files. I suggest delete them.

Checkpoint

At this point, tomcat should start with the default configuration. It is a good idea to make a little test prior to further testing.

Log in as the tomcat user and run the server:

tomcat@machine:/usr/local/share/apache-tomcat-7.0.22/bin> ./startup.sh 
Using CATALINA_BASE:   /usr/local/share/apache-tomcat-7.0.22
Using CATALINA_HOME:   /usr/local/share/apache-tomcat-7.0.22
Using CATALINA_TMPDIR: /usr/local/share/apache-tomcat-7.0.22/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /usr/local/share/apache-tomcat-7.0.22/bin/bootstrap.jar:/usr/local/share/apache-tomcat-7.0.22/bin/tomcat-juli.jar

Open a web browser and point it to the http://localhost:8080 port. It should show a welcome message of tomcat. If not, check out what is wrong. A simple lynx http://localhost:8080 should return something understandable.

Fine-tunning configuration

Location of log files

SuSE has all their log files under /var/log, so I prefer respect this practice and move the logs of apache to this location. Now they are under /usr/local/share/tomcat/logs.

First, create a proper directory under /var/log, let's say /var/log/tomcat:

# mkdir /var/log/tomcat
# chown tomcat:tomcat /var/log/tomcat

Then, open the file CATALINA_HOME/conf/logging.properties –CATALINA_HOME is the directory Tomcat is installed, and is refered as this in the documentation– and modify the following entries:

1catalina.org.apache.juli.FileHandler.level = FINE
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.
 
2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.prefix = localhost.

When it appears ${catalina.base}/logs it should appear the new directory, /var/log/tomcat.

Open the “server.xml” file and change locate the “logs” old directory and replace by the new one, /var/log/tomcat. I've replace the following entries:

  <Valve className="org.apache.catalina.valves.AccessLogValve" 
         directory="logs"
         prefix="localhost_access_log." suffix=".txt"

Go to the bin directory and open the file catalina.sh. There is a configuration for the console of the server there. Locate this entry:

if [ -z "$CATALINA_OUT" ] ; then
  CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out
fi

And change for:

if [ -z "$CATALINA_OUT" ] ; then
  CATALINA_OUT=/var/log/tomcat/catalina.out      
fi

Delete the content of the “logs” directory and start again the server. If after running the server still appear content, you should check the configuration or the configuration.

If the checking were successful, remove the logs directory and create a symbolic link with the same name: just in case other user logged in the system and searched for the directory where it is supposed to be in a normal installation.

Location of config files

Another step is to change the location of the config files and put them under /etc/tomcat: it is the usual point where a normal user should look for.

Creation of the directory under /etc
machine:/etc # mkdir tomcat
machine:/etc # chown tomcat:tomcat tomcat 
Move the contents to the new location

Log in as the tomcat user:

tomcat@machine:/usr/local/share/tomcat/conf> cp * /etc/tomcat/ -R
tomcat@machine:/usr/local/share/tomcat> tar -czf conf_orig.tgz conf/
tomcat@machine:/usr/local/share/tomcat> rm -r conf
tomcat@machine:/usr/local/share/tomcat> ln -s /etc/tomcat/ conf 

Create a Service so that it will start automatically

In general, it is a good idea to create a service that will start automatically when the server starts. And that will be gently stopped when the servers is shut down.

How to do this??

One idea is to search in internet. But bear in mind that most modern Linux distributions comes with examples of services ready to customize for your needs. These examples are common called as skeletons and normally live –or rest, because they are skeletons, aren't they??– in /etc.

Mess around the /etc directory of your installation or check /etc/rc.d/ or /etc/init.d in order to locate those scripts.

Here I put the script I created for SuSE

#!/bin/sh
#
#     Script for start/stop tomcat. Based on template "skeleton"
#
#
#     This library is free software; you can redistribute it and/or modify it
#     under the terms of the GNU Lesser General Public License as published by
#     the Free Software Foundation; either version 2.1 of the License, or (at
#     your option) any later version.
#			      
#     This library is distributed in the hope that it will be useful, but
#     WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#     Lesser General Public License for more details.
#      
#     You should have received a copy of the GNU Lesser General Public
#     License along with this library; if not, write to the Free Software
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
#     USA.
#
# /etc/init.d/FOO
#   and its symbolic link
# /(usr/)sbin/rcFOO
#
#
# LSB compatible service control script; see http://www.linuxbase.org/spec/
# 
#
### BEGIN INIT INFO
# Provides:          tomcat
# Required-Start:    $syslog $remote_fs apache
# Should-Start:      $time ypbind smtp
# Required-Stop:     $syslog $remote_fs
# Should-Stop:       
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: Tomcat
# Description:       Start the Tomcat Application Server
### END INIT INFO
# 
# Any extensions to the keywords given above should be preceeded by 
# X-VendorTag- (X-UnitedLinux- X-SuSE- for us) according to LSB.
# 
# Notes on Required-Start/Should-Start:
# * There are two different issues that are solved by Required-Start
#    and Should-Start
# (a) Hard dependencies: This is used by the runlevel editor to determine
#     which services absolutely need to be started to make the start of
#     this service make sense. Example: nfsserver should have
#     Required-Start: $portmap
#     Also, required services are started before the dependent ones.
#     The runlevel editor will warn about such missing hard dependencies
#     and suggest enabling. During system startup, you may expect an error,
#     if the dependency is not fulfilled.
# (b) Specifying the init script ordering, not real (hard) dependencies.
#     This is needed by insserv to determine which service should be
#     started first (and at a later stage what services can be started
#     in parallel). The tag Should-Start: is used for this.
#     It tells, that if a service is available, it should be started
#     before. If not, never mind.
# * When specifying hard dependencies or ordering requirements, you can 
#   use names of services (contents of their Provides: section)
#   or pseudo names starting with a $. The following ones are available
#   according to LSB (1.1):
#	$local_fs		all local file systems are mounted
#				(most services should need this!)
#	$remote_fs		all remote file systems are mounted
#				(note that /usr may be remote, so
#				 many services should Require this!)
#	$syslog			system logging facility up
#	$network		low level networking (eth card, ...)
#	$named			hostname resolution available
#	$netdaemons		all network daemons are running
#   The $netdaemons pseudo service has been removed in LSB 1.2.
#   For now, we still offer it for backward compatibility.
#   These are new (LSB 1.2):
#	$time			the system time has been set correctly	
#	$portmap		SunRPC portmapping service available
#   UnitedLinux extensions:
#	$ALL			indicates that a script should be inserted
#				at the end
# * The services specified in the stop tags 
#   (Required-Stop/Should-Stop)
#   specify which services need to be still running when this service
#   is shut down. Often the entries there are just copies or a subset 
#   from the respective start tag.
# * Should-Start/Stop are now part of LSB as of 2.0,
#   formerly SUSE/Unitedlinux used X-UnitedLinux-Should-Start/-Stop.
#   insserv does support both variants.
# * X-UnitedLinux-Default-Enabled: yes/no is used at installation time
#   (%fillup_and_insserv macro in %post of many RPMs) to specify whether
#   a startup script should default to be enabled after installation.
#   It's not used by insserv.
#
# Note on runlevels:
# 0 - halt/poweroff 			6 - reboot
# 1 - single user			2 - multiuser without network exported
# 3 - multiuser w/ network (text mode)  5 - multiuser w/ network and X11 (xdm)
# 
# Note on script names:
# http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/scrptnames.html
# A registry has been set up to manage the init script namespace.
# http://www.lanana.org/
# Please use the names already registered or register one or use a
# vendor prefix.
 
TOMCAT_HOME=/usr/local/share/tomcat
test -d $TOMCAT_HOME || { echo "$TOMCAT_HOME is not a directory. Please check." 
;
	if [ "$1" = "stop" ]; then exit 0;
	else exit 5; fi; }
# Check for missing binaries (stale symlinks should not happen)
# Note: Special treatment of stop for LSB conformance
TOMCAT_BIN=$TOMCAT_HOME/lib/catalina.jar
test -s $TOMCAT_BIN || { echo "$TOMCAT_BIN not found. Is tomcat properly install
ed?"; 
	if [ "$1" = "stop" ]; then exit 0;
	else exit 5; fi; }
 
# Check for existence of needed config file and read it
TOMCAT_CONFIG=$TOMCAT_HOME/conf/server.xml
test -r $TOMCAT_CONFIG || { echo "$TOMCAT_CONFIG not exists or not readable";
	if [ "$1" = "stop" ]; then exit 0;
	else exit 6; fi; }
 
# Source LSB init functions
# providing start_daemon, killproc, pidofproc, 
# log_success_msg, log_failure_msg and log_warning_msg.
# This is currently not used by UnitedLinux based distributions and
# not needed for init scripts for UnitedLinux only. If it is used,
# the functions from rc.status should not be sourced or used.
#. /lib/lsb/init-functions
 
# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     be verbose in local rc status and clear it afterwards
#      rc_status -v -r  ditto and clear both the local and overall rc status
#      rc_status -s     display "skipped" and exit with status 3
#      rc_status -u     display "unused" and exit with status 3
#      rc_failed        set local and overall rc status to failed
#      rc_failed <num>  set local and overall rc status to <num>
#      rc_reset         clear both the local and overall rc status
#      rc_exit          exit appropriate to overall rc status
#      rc_active        checks whether a service is activated by symlinks
. /etc/rc.status
 
# Reset status of this service
rc_reset
 
# Return values acc. to LSB for all commands but status:
# 0	  - success
# 1       - generic or unspecified error
# 2       - invalid or excess argument(s)
# 3       - unimplemented feature (e.g. "reload")
# 4       - user had insufficient privileges
# 5       - program is not installed
# 6       - program is not configured
# 7       - program is not running
# 8--199  - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
# 
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signaling is not supported) are
# considered a success.
 
case "$1" in
    start)
	echo -n "Starting Tomcat "
	## Start daemon with startproc(8). If this fails
	## the return value is set appropriately by startproc.
	#/sbin/startproc -u tomcat -g tomcat $TOMCAT_HOME/bin/startup.sh
 
	su tomcat -c $TOMCAT_HOME/bin/startup.sh
 
	# Remember status and be verbose
	rc_status -v
	;;
    stop)
	echo -n "Shutting down Tomcat "
	## Stop daemon with killproc(8) and if this fails
	## killproc sets the return value according to LSB.
	#/sbin/startproc -u tomcat -g tomcat $TOMCAT_HOME/bin/shutdown.sh
 
	su tomcat -c $TOMCAT_HOME/bin/shutdown.sh
 
	# Remember status and be verbose
	rc_status -v
	;;
    restart)
	## Stop the service and regardless of whether it was
	## running or not, start it again.
	$0 stop
	$0 start
	# Remember status and be quiet
	rc_status
	;;
    *)
	echo "Usage: $0 {start|stop|restart}"
	exit 1
	;;
esac
rc_exit

Integration with Apache

Due to the fact that I am using apache at the same time in the same machine, Tomcat will act only as the server of the JSP pages, delegating all the static content to apache.

You have to have apxs installed in your system. If you are running apache, it is achieved installing through yast the module apache2-devel.

Tomcat connector mod-jk

The only way to integrate apache with tomcat is to use mod_jk. Here is the documentation:

http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html

And you have to google the download location. I've downloaded the source code and here are the instructions to compile it:

Installing and compiling mod_jk

Once you have the apxs2 program installed and the source code of the mod_jk, you are prepared to compile it:

$ cd native 
$ ./configure --with-apxs=/usr/sbin/apxs2
$ su
# make install

http://tomcat.apache.org/connectors-doc-archive/jk2/jk/quickhowto.html

Things to do in apache

In the apache configuration directory, create a file called “workers.properties” with the following content:

# Define 1 real worker using ajp13
worker.list=worker1
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=300 

At least the following configuration must be put under apache:

# Load mod_jk module
# Under SuSE this is carried out by sysconfig/apache2
# Update this path to match your modules location
LoadModule jk_module libexec/mod_jk.so

# Under SuSE this is carried out by sysconfig/apache2
# Declare the module for <IfModule directive>
AddModule mod_jk.c

# Where to find workers.properties
# Update this path to match your conf directory location (put workers.properties next to httpd.conf)
JkWorkersFile /etc/httpd/conf/workers.properties

# Where to put jk logs
# Update this path to match your logs directory location (put mod_jk.log next to access_log)
JkLogFile /var/log/httpd/mod_jk.log

# Set the jk log level [debug/error/info]
JkLogLevel info

# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"

# Send everything for context /examples to worker named worker1 (ajp13)
JkMount /examples/* worker1

# In installation with virtual servers, it allows to respond to 
# http://wateverthedomainwillbe/examples 
# If not, you have to put this directive (JkMountCopy) under 
# the VirtualHost directive you want to use 
JkMountCopy All

There are several ways to organize it. Under SuSE, the best way is the following:

  • under /etc/sysconfig/apache2 modify the line APACHE_MODULES and add at the end the “jk”: this will instruct to load the mod_jk.so module also and modify /etc/apache2/sysconfig/loadmodule.conf according to that
  • also modify the variable APACHE_CONF_INCLUDE_FILES to include a file that will be called mod_jk.conf
  • create the file /etc/apache2/mod_jk.conf to include the configuration proper to the mod_jk.so module. Please add <IfModule mod_jk.c> and </IfModule> directives to better exclude by simply removing the module from loading

Security Issues

Deactivate the listening through the 8080 port

Disconnect the default Connector port under tomcat: the port 8080. If you aren't gonna use it, the obvious is to disconnect it.

Under TOMCAT_HOME, locate the file server.xml and comment out the following lines:

    <!-- Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" / -->

Delete the "examples" application

Go to TOMCAT_HOME/webapps and delete the directory “examples”. Why? Because is a well-known application that do things. Some example applications aren't built with security in mind, so it is a good idea to delete them.

Test and conclusion

Test, test, test… In every step you take in this issue, try to test if you are doing the correct!!! This is the best advice I can give you in order to succeed in such projects.

Anyway, the last step is to test the issue. I've opened a browser, point it to http://mydomain.com/examples/whateveryouwant and you should have a fantastic error screen directly from tomcat (instead of a 404 coming from apache).

You can elaborate this much –as I did– and change the “examples” you find in the mod_jk.conf file for “docs”: this will point to an application called “docs” that is in Tomcat. If you do this, you cant point your browser to http://mydomain.com/docs/index.html and get the tomcat documentation that comes with the tomcat installation:

Conclusion

In this document I've tried to explain how to install tomcat to serve as a backend for an Apache http server, so it serves only certain types of pages.

The explanation is made from the ground, as if there were no prior knowledge of apache nor tomcat. I hope I achieved this. If not, drop me some lines in the Discussion below. Anyway, any comment or suggestion will help.

Documentation

I checked out this document: http://www.digitalsanctum.com/2007/08/18/20-tips-for-using-tomcat-in-production/. Unless it is a bit outdated (2007), many of the ideas depicted there are still valid.

Of course, I checked also the Apache Tomcat documentation: http://tomcat.apache.org/tomcat-7.0-doc/index.html

And have a look at this: http://tomcat.apache.org/connectors-doc/reference/apache.html. It is the documentation of the mod_jk module and it is very important if you want to have your own installation.

~~DISQUS~~

java/installationunderlinux.txt · Last modified: 2022/12/02 22:02 by 127.0.0.1