Running Java and Tomcat on a Virtual Server

Introduction

A Virtual Server is ideally suited to running a dedicated install of Tomcat for hosting J2EE-based applications. Here's how to set it up with Whitebox Enterprise Linux (a free rebuild of RedHat Enterprise Linux without any of the support or cost).

Buying the server

Decide how much memory you'll need; you can run in 128MB, but depending on the application complexity you would be well advised to buy 256MB or 512MB. If you guess too small, your memory quota can easily be expanded. Fill in our application form and we'll get you set up with a Virtual Server.

For my example here, I'm using womble.vs.mythic-beasts.com, a 64MB virtual server.

Installing Java and Tomcat

Depending on which kernel your Virtual Server is running, it may be necessary to disable the thread-local storage features of the system C library, since User-Mode Linux presently doesn't support this and until recently UML kernels could crash if the thread-local storage versions were used. Check with support for more details, but for safety it's easiest just to disable the TLS libraries:

# mv /lib/tls /lib/tls.bak

(This, and other setup commands, should be run as root logged into your Virtual Server. "#" is the root prompt, and anything in this font is a command to type.)

Firstly you'll need to download both a Java SDK and the version of Tomcat you'd like to use.

Java 1.4.2 and Tomcat 5.0

This is the latest stable release of Java and Tomcat recommended for production use. To download Java you have to agree to the license agreement at, http://java.sun.com/j2se/1.4.2/download.html; click the download link and agree to the license agreement. Choose the Linux platform SDK, and copy the link location for the self extracting file. On your virtual server download this link:

# wget -O j2sdk-linux.bin http://192.18.97.222/ECom/EComTicketServlet/BEGINjsecom15a.sun.com-aa96%3A4144504d%3Aacd93f6445e5437/-2147483648/515342331/1/489890/489698/515342331/2ts+/westCoastFSEND/j2sdk-1.4.2_05-oth-JPR/j2sdk-1.4.2_05-oth-JPR:4/j2sdk-1_4_2_05-linux-i586.bin

Similarly download Tomcat 5.0.whatever; here I've used 5.0.28:

# wget -O tomcat5.0.28.tar.gz http://ftp.plig.net/pub/apache/dist/jakarta/tomcat-5/v5.0.28/bin/jakarta-tomcat-5.0.28.tar.gz

We should now have two files: a Java SDK installer, and a Tomcat archive:

# ls -l
total 46084
-rw-r--r--    1 root     root          815 May  5 21:54 anaconda-ks.cfg
-rw-r--r--    1 root     root        19390 May  5 21:54 install.log
-rw-r--r--    1 root     root         3238 May  5 21:46 install.log.syslog
-rw-r--r--    1 root     root     36384457 Jun  9 21:06 j2sdk-linux.bin
-rw-r--r--    1 root     root     10718313 Aug 29 04:13 tomcat5.0.28.tar.gz

Installing Java

The next stage is to install Java. We need to make it executable, run the binary and let it unzip the archive for us. Then we move it into /usr/local/java:

# chmod +x j2sdk-linux.bin
# ./j2sdk-linux.bin
              Sun Microsystems, Inc.
          Binary Code License Agreement
                   for the

JAVATM 2 SOFTWARE DEVELOPMENT KIT (J2SDK), STANDARD
EDITION, VERSION 1.4.2_X

... lots of licensing waffle ...

For inquiries please contact: Sun Microsystems, Inc., 4150
Network Circle, Santa  Clara, California 95054, U.S.A.
(LFI#140023/Form ID#011801)

Do you agree to the above license terms? [yes or no]
yes
Unpacking...
Checksumming...

... big list of files it's just unzipped ...

Creating j2sdk1.4.2_05/jre/lib/jsse.jar
Creating j2sdk1.4.2_05/jre/lib/charsets.jar
Creating j2sdk1.4.2_05/jre/lib/ext/localedata.jar
Creating j2sdk1.4.2_05/jre/lib/plugin.jar
Creating j2sdk1.4.2_05/jre/javaws/javaws.jar
Done.

# mv j2sdk1.4.2_05 /usr/local/java

Now we add Java to the system path, for all users:

# cat >> /etc/profile
PATH=$PATH:/usr/local/java/bin
export PATH

JAVA_HOME=/usr/local/java
export JAVA_HOME

JDK_HOME=/usr/local/java
export JDK_HOME

Type Ctrl-D ("^D") to finish the above.

Now, if we log out and in again, Java should Just Work:

# java -version
java version "1.4.2_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)

Installing Tomcat

Tomcat is a little easier to install. We extract the archive and move the resulting directory to /usr/local:

# tar -zxf tomcat5.0.28.tar.gz
# mv jakarta-tomcat-5.0.28 /usr/local/tomcat

Now we can start up Tomcat and make sure everything is running:

# /usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JAVA_HOME:       /usr/local/java
# links http://localhost:8080

Links is a text-mode web browser which is useful for quickly checking on pages while logged in to your Virtual Server. Here it should show something like this:

                                                     Apache Tomcat/5.0.28
          
   The Mighty Tomcat - MEOW! Apache Tomcat/5.0.28         The Jakarta Project

   ........................          If you're seeing this page via a web
   .Administration        .          browser, it means you've setup Tomcat
   ........................             successfully. Congratulations!
   .Status                .
   .Tomcat Administration .       As you may have guessed by now, this is the
   .Tomcat Manager        .       default Tomcat home page. It can be found
   .                      .       on the local filesystem at:
   ........................

Type Ctrl-C or "q" to exit Links.

Setting up for Production.

Whilst Tomcat is running, the default firewall on the machine is blocking connections to it, so it's not externally visible. Tomcat is also running as root so if it's compromised, the whole machine will be open to the attacker. We now have to build jscv, the Java Service Daemon, to run it. This also creates a startup script to install Tomcat as a daemon; however we ignore it, because it's aimed at Tomcat 4 and won't work with this version.

# cd /usr/local/tomcat/bin/
# tar -zxf jsvc.tar.gz
# cd jsvc-src/
# autoconf
# chmod +x configure
# ./configure
*** Current host ***

... compilation stuff ...

*** All done ***

Now you can run "make" and build the daemon:

# make
make -C native all

... building stuff ...

make[1]: Leaving directory `/usr/local/tomcat/bin/jsvc-src/native'
# cp jsvc ..
# cd ..

Now we can tell Tomcat to start up as a different user bound on port 80. We edit /usr/local/tomcat/conf/server.xml and change the port to 80. Using a text editor (try pico unless you already have a favourite), change:

<Connector port="8080"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               debug="0" connectionTimeout="20000"
               disableUploadTimeout="true" />

to

<Connnector port="80"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               debug="0" connectionTimeout="20000"
               disableUploadTimeout="true" />

Now we can start Tomcat running as the unprivileged apache user on port 80, so it works just like a normal web server. We also want to install Tomcat as a system service so it starts on machine boot. I'm not going to explain how to modify the file supplied by Tomcat to make it work; just download mine which has had the paths fixed for this install, and chkconfig info added. We also need to grant the apache user rights to all the Tomcat files. So:

# wget -O /etc/init.d/tomcat https://static.mythic-beasts.com/support/topics/vds_java/tomcat-initscript.sh
# chmod +x /etc/init.d/tomcat
# chkconfig --add tomcat
# chkconfig --level 345 tomcat on
# chown -R apache:apache /usr/local/tomcat
# chown -R root:root /usr/local/tomcat/bin
# chown -R root:root /usr/local/tomcat/common
# /etc/init.d/tomcat start

Tomcat is now up and running on port 80, and visible to the world (the default firewall does not block port 80).

Securing

Now we should secure our Tomcat and linux installation from the world. Remove all the web-apps we're not using:

# rm -rf balancer/ jsp-examples/ servlets-examples/ tomcat-docs/ webdav/

To secure the Whitebox Enterprise Linux install, we set up yum to point at the esat mirror. Just copy my configuration:

# wget -O /etc/yum.conf https://static.mythic-beasts.com/support/topics/vds_java/yum.conf

You'll also need to make sure that /mirror, the directory containing mirrored Linux distributions, is mounted in your Virtual Server. This should be set up by our installer, but if it is not, create the mountpoint directory by doing,

# mkdir /mirror

add to /etc/fstab the line,

/mirror                 /mirror                 hostfs  ro              0 0

and mount the mirrors with,

# mount /mirror

To fully patch the machine, run yum and tell it to answer yes to all questions:

# yum -y update
Gathering header information file(s) from server(s)
Server: White Box Enterprise Linux 3.0 - i386 - Base
Server: White Box Enterprise Linux 3.0 - i386 - Released Updates
Finding updated packages
Downloading needed headers

... lots of downloading activity ...

Resolving dependencies

... a long wait as there are many packages to do ...

Dependencies resolved
I will do the following:

... big list of packages ...

Downloading Packages

... wait while it downloads packages ...

Running test transaction:
Test transaction complete, Success!

... installing packages ...

Transaction(s) Complete

We tell the machine to email us its messages. Edit /etc/aliases to add:

# Person who should get root's mail
root:          your@email.address

Scripting the updates

We then script the patching of the machine because we don't want to be hacked into. This isn't necessary and carries a small risk of the machine becoming unavailable due to a poor update, but helps to protect against becoming unavailable due to being hacked into by a script kiddie.

# cat > /etc/cron.daily/update
#!/bin/bash
yum -y update
mv /lib/tls /lib/tls-`date -I`
^D
# chmod 755 /etc/cron.daily/update

We're finished.