Excelsior Logo Home
Buy   
Download   
Support   
 Forum   
Blog   

Cat in the Cloud: Apache Tomcat in Amazon EC2

Part II - Taking control over your Java stack

Last update: 02-May-2012

By Dmitry LESKOV

This is the second part of a step-by-step guide for Java Web application developers wanting to get their feet wet in the Amazon cloud. Part I discussed the very basic topics such as creating an Amazon EC2 instance and installing Tomcat from the official Amazon Linux repo. Part III will take on the more advanced topics such as making Tomcat listen on port 80.

As I briefly mentioned in the first part, Amazon Linux repos contain Java (in fact, a JRE is preinstalled), Tomcat, and many supplementary libraries such as log4j. So why write this part of the series at all?

First and foremost, Amazon Linux repositories contain customized builds of specific versions of the respective software, which may not be what your application requires. As of Amazon Linux 2012.03, these are an OpenJDK build of Java 1.6.0_22 with security patches applied, and some builds of Apache Tomcat 6.0.35 and 7.0.25 (jar files differ from the official Apache downloads).

Second, these packages are controlled by the package management system and may therefore get upgraded when you update the system, inadvertently breaking things.

Whether you want to use the latest and greatest versions of everything for that shiny new app you are building from scratch, or you have been given the task of moving into the cloud a legacy application requiring an older version of Java and/or Tomcat, or you prefer the official builds because they get the security updates first, this article is for you.

If those are not enough reasons, here are two more.

  • The filesystem layouts and configuration files of these packages are substantially tweaked. You'd need to wrap your head around all those changes.
  • The number of package dependencies is overwhelming. Installing the tomcat6 package will bring over 60 other packages onto a fresh Amazon Linux instance, including the entire print stack from GhostScript to CUPS (Common Unix Printing System) to foomatic (database of printers and printer drivers). Are there (m)any web apps that print anything on the server side?

    Note that the command

    yum deplist package

    only shows the immediate dependencies of package. To find out what would have actually been installed, issue the following command:

    echo n | sudo yum install package

Installing Oracle Java

Update 02-May-2012: As of Amazon Linux 2012.03, the amzn-nosrc repository, which used to contain a fresh Oracle JRE, is empty:

yum --disablerepo="*" --enablerepo=amzn-nosrc repolist
   .  .  .
repo id                           repo name                               status
amzn-nosrc                        amzn-nosrc-Base                         0
repolist: 0

If this happens to be your case, skip to the next subsection.

Otherwise, check if a fresh Oracle JRE is available in that repository:

yum --enablerepo=amzn-nosrc info jre
   .  .  .
Version     : 1.6.0_29
   .  .  .

It is the original RPM as released by Oracle. If you don't mind having your Java installation exposed to the automatic system update mechanism, you may install it as follows:

sudo yum --enablerepo=amzn-nosrc install jre

It will appear under /usr/java/jre1.6.0_29. This JRE, however, may be upgraded when you update the system. If this is not acceptable, or if you need the full JDK or some other version of Oracle Java, read on. Otherwise you may go straight to the section on manual Tomcat installation.

JDK or JRE?

Most Tomcat installation guides recommend that you install the JDK. However, the official Apache Tomcat FAQ states: "Tomcat 4 requires the full JDK. Tomcat 5.5 onwards will work with a JRE or a JDK."

There is one exception that the FAQ does not mention though: running Tomcat in debug mode requires the JDK. If you plan to develop "in the cloud", you may want to install the full JDK on your development instances.

You also may be under the impression that the JRE does not contain the Hotspot Server VM. But this is only true for the 32-bit Windows JRE. (Source: HotSpot VM FAQ)

RPM or Self-Extracting?

Oracle's Java downloads for Linux come in pairs: an RPM and a self-extracting archive. Again, most other guides suggest that you download the former if your flavor of Linux supports RPMs. But if you inspect the RPM pre/post-install scripts, you will notice that they primarily fiddle with Gnome desktop integration, Java Web Start, making jars directly executable, and other stuff that is pretty much irrelevant for running a Tomcat server. I have only spotted one difference that may be of significance: the location of the preferences directory (/etc/.java/.systemPrefs/ if you install from RPM, or .systemPrefs/ under the root directory of an extracted SFX, e.g. jre1.6.0_32/.systemPrefs/.)

To sum it up, for production instances I recommend that you download and install the self-extracting JRE and configure Tomcat to use it. You need not remove the preinstalled OpenJDK if you wish to use it for running, for example, the command-line EC2 API tools.

Download and Install

  1. To download the latest update release of a maintained major Java version, go to the Oracle Java SE download page, scroll down to the desired version and click the Download button.

    To download a prior version of Java, go to the Oracle Java Archive instead and locate the specific version you need.

  2. Select Accept License Agreement (technically, you are supposed to read it first. ;) )
  3. Download the self-extracting Linux x86 JRE binary, e.g. jre‑6u32‑linux‑i586.bin.
  4. Upload the downloaded binary to your instance (refer to the SSH inset in the previous article for instructions on uploading files via SSH).
  5. Log in to your instance via SSH, make the uploaded file executable and run it:
    chmod u+x jre-6u32-linux-i586.bin
    ./jre-6u32-linux-i586.bin
  6. The archive will self-extract into a subdirectory of the current directory, in this case ./jre1.6.0_32. Upon successful extraction, move that directory to a common location and lock it down by setting file ownership and permissions:
    sudo mv ./jre1.6.0_32 /opt
    sudo chown -R root:root /opt/jre1.6.0_32
    sudo chmod -R go-w /opt/jre1.6.0_32
    

Replacing the OpenJDK Java Gracefully

Amazon Linux relies on the alternatives system for managing co-existence of multiple software packages providing the same functionality. To register Oracle Java as an alternative, issue the following command, making sure to replace paths accordingly and use priority (“16032” below) matching the version you are registering.

sudo alternatives \
  --install /usr/bin/java java /opt/jre1.6.0_32/bin/java 16032 \
  --slave /usr/lib/jvm/jre jre /opt/jre1.6.0_32

(alternatives --display java will display many more slave links, but of them, only jre is essential for running Tomcat.)

If you register a version newer than 1.6.0, it will override the preinstalled OpenJDK JRE automatically:

java -version
java version "1.6.0_32"
Java(TM) SE Runtime Environment (build 1.6.0_32-b05)
Java HotSpot(TM) Client VM (build 20.7-b02, mixed mode, sharing)

Otherwise, you need to issue the following command:

sudo alternatives --set java java-path
where java-path is the path you have specified in alternatives ‑‑install, e.g. /opt/j2re1.4.2_30/bin/java.

Installing Any Version of Tomcat

  1. If you have followed the first article of this series, Tomcat installed from the Amazon Linux repo may still be running on your instance. Make sure to stop it and disable automatic startup (replace “tomcat6” with “tomcat7” in the commands below if you have installed Tomcat 7):

    sudo service tomcat6 stop
    sudo chkconfig tomcat6 off
    chkconfig --list

    Expected output:

       .  .  .
    tomcat6        	0:off	1:off	2:off	3:off	4:off	5:off	6:off
       .  .  .
    
  2. Go to the official Apache Tomcat Web site, and copy the URL of the desired binary distribution. Then fetch it to your instance and unpack to the /opt directory:

    wget -c http://mirror/path/apache-tomcat-version.tar.gz
    sudo tar xvfz apache-tomcat-version.tar.gz -C /opt

    This will extract Tomcat into the /opt/apache-tomcat-version/ directory. You may wish to create a version-agnostic symbolic link to it. (This will enable you to quickly switch between multiple Tomcat installations if needed):

    sudo ln -s /opt/apache-tomcat-version /opt/tomcat 
  3. If you have installed Oracle Java, but have not made it the default alternative, JAVA_HOME still points to the location of the preinstalled OpenJDK JRE. To point the Tomcat startup script to the desired Java runtime, create a file setenv.sh in the Tomcat bin/ directory with the following contents:

    #!/bin/sh
    export JAVA_HOME=Java-runtime-location

    For instance:

    sudoedit /opt/tomcat/setenv.sh
    #!/bin/sh
    export JAVA_HOME=/opt/jre1.6.0_32
  4. It is a good idea to create a dedicated user account to run Tomcat. If you have previously installed the tomcat6 package from the Amazon Linux repo, you already have a system group tomcat and a system user tomcat. (They are not removed even if you uninstall the package.) Otherwise, you may create them as follows:
    sudo /usr/sbin/groupadd -g 91 -r tomcat 
    sudo /usr/sbin/useradd -c "Apache Tomcat" -u 91 -g tomcat -s /sbin/nologin -r -d /opt/tomcat tomcat
    It makes sense to maintain the same user and group IDs across all EC2 instances so as to care less about file ownership. The "official" tomcat6 package uses 91 as user and group ID, so you may be more or less sure that installation of other packages won't adversely interfere with this selection. If you omit the respective options, smallest values greater than any existing IDs will be selected.
  5. Set file ownership and permissions. Recommendations in Tomcat documentation, books, and on the Internet vary. I prefer using group permissions, as there may be a need to grant other applications access.

    1. All Tomcat files and directories shall belong to the superuser, and only the superuser shall have write access to the core files residing in bin/ and lib/.
    2. On a development/test EC2 instance you may want to leave auto-deployment enabled and the Manager web app installed. The members of the tomcat group shall then be allowed to write to the following directories: conf/, logs/, temp/, webapps/, and work/.
    cd /opt/tomcat
    sudo chown -R root:tomcat *
    sudo chmod -R go-w bin lib
    sudo chmod -R g+rw conf logs temp webapps work
    

    Files under conf/ are only owner-accessible by default, hence the explicit setting of group read permissions in the last command.

    On a production instance, it makes sense to restrict file permissions. This will be discussed in the respective section of the next article.

  6. Create a minimalistic start/stop script:

    sudoedit /etc/init.d/tomcat
    #!/bin/sh
    # Baseline Apache Tomcat start/stop script
    #
    # chkconfig: 345 80 20
    # description: Apache Tomcat
    
    case $1 in
    start)
            /bin/su -s /bin/sh -l tomcat -c /opt/tomcat/bin/startup.sh
            ;;
    stop)
            /bin/su -s /bin/sh -l tomcat -c /opt/tomcat/bin/shutdown.sh
            ;;
    restart)
            /bin/su -s /bin/sh -l tomcat -c /opt/tomcat/bin/shutdown.sh
            /bin/su -s /bin/sh -l tomcat -c /opt/tomcat/bin/startup.sh
            ;;
    esac
    exit 0
    Group and world should not have write permissions to it, but just to be safe:
    sudo chmod go-w /etc/init.d/tomcat
  7. Try to start the Tomcat service:
    sudo service tomcat start
    Using CATALINA_BASE:   /opt/tomcat
    Using CATALINA_HOME:   /opt/tomcat
    Using CATALINA_TMPDIR: /opt/tomcat/temp
    Using JRE_HOME:        /opt/jre1.6.0_32
    Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
  8. Now try connecting your browser to port 8080 on your instance. You should see the default Tomcat home page.

    If you cannot connect:

    • Check that Tomcat has indeed started and is listening on port 8080:

      sudo fuser -v -n tcp 8080

      Expected output:

                           USER        PID ACCESS COMMAND
      8080/tcp:            tomcat      pid F.... java
    • Check that your instance's security group permits inbound connections to port 8080.
  9. To have Tomcat start automatically on instance boot, issue the following command:

    sudo /sbin/chkconfig --add tomcat

    If you receive a message "service tomcat does not support chkconfig", check that the following comments are present near the top of your Tomcat service script /etc/init.d/tomcat:

    # chkconfig: 345 80 20
    # description: Apache Tomcat
    

    Verify that Tomcat has been added to the list of managed services:

    chkconfig --list
       .  .  .
    tomcat        	0:off	1:off	2:off	3:on	4:on	5:on	6:off
       .  .  .
    

Summary

You have learned how to manually install any version of Oracle Java and Apache Tomcat to an Amazon EC2 instance running Amazon Linux.

However, the baseline configuration described above needs some tweaking before you roll it into production. In the follow-up article, we'll discuss advanced configuration topics and the protection of your Web applications.

Was the above article useful? If yes, we have more content for you!

First of all, here are the links to Part I and Part III of the series.

Check out other articles written by Excelsior staff members:

Home | Company | Products | Services | Resources | Contact

Store | Downloads | Support | Forum | Blog | Sitemap

© 1999-2013 Excelsior LLC. All Rights Reserved.