Installing Java 8 and Tomcat 8 on Debian Wheezy

Feb 01, 2015

Installing Java 8

By default, Debian repositories only have Open JDK and on Wheezy, the Open JDK version is the equivalent of Java 7. To get the latest Java 8, we need to install it manually. First download the Java 8 server JRE which comes with JVM monitoring tools. Or you could just download the Java 8 JDK which includes those monitoring tools and more. I prefer to install only the bare minimum setup that is necessary.

When manually installing software on Linux, it is recommended that it go into /opt directory. So unpack the JRE or JDK into /opt.

Create a symbolic link "java8" pointing to the JRE/JDK directory. This will make it easier when installing updates to the JRE/JDK. All Java dependent applications will refer to the symbolic link and when you do update the JRE/JDK, you don’t need to update the path to Java for all those applications. You just need to update the symbolic link.

cd /opt
sudo ln -s jdk1.8.0_25 java8

Add the Java bin directory to your PATH so that the Java commands are available to you. Edit your .profile file

vi ~/.profile

Then add the bin directory to PATH:


Installing Tomcat 8

Download the latest Tomcat 8 from here. Extract to /opt:

cd /opt
sudo wget
sudo tar xzf apache-tomcat-8.0.15.tar.gz

(Optionally, you can verify the PGP signatures for the Tomcat download. The verification process is explained here. Since we are doing a manual install as opposed to installing from Debian repositories, verifying signatures is a good idea. Packages in Debian repositories are already verified by package maintainers).

The Tomcat documentation recommends having two separate directories - one for Tomcat binaries, and the other for the config files and deployment directories. This will make it easier to make upgrades to Tomcat. When installing a newer version of tomcat, you don’t need to touch the config files or the deployed wars. You just need to update the Tomcat binaries.

For Tomcat binaries, create a symbolic link called tomcat-home:

sudo ln -s apache-tomcat-8.0.15 tomcat-home

For the config files and deployment directories, create a new directory called tomcat-base and create the necessary directories inside it:

sudo mkdir tomcat-base
sudo cp -r tomcat-home/conf/ tomcat-base/
sudo cp -r tomcat-home/webapps/ tomcat-base/
sudo mkdir tomcat-base/bin
sudo mkdir tomcat-base/lib
sudo mkdir tomcat-base/logs
sudo mkdir tomcat-base/work
sudo mkdir tomcat-base/temp

You can remove the web applications inside webapps if you are not going to use them.

Securing Tomcat

Create a new user and group to run the Tomcat server:

sudo addgroup --system "tomcat"

sudo adduser --system --home /opt/tomcat-home --no-create-home \
	--ingroup "tomcat" --disabled-password --shell /bin/false \

sudo chown -R tomcat /opt/tomcat-base /opt/tomcat-home /opt/tomcat-home/*
sudo chgrp -R tomcat /opt/tomcat-base /opt/tomcat-home /opt/tomcat-home/*

For security reasons, the Tomcat user should not be able to modify any configuration files. Change permissions so that only root can edit:

sudo chown -Rh root:tomcat /opt/tomcat-home/conf /opt/tomcat-home/lib /opt/tomcat-home/bin
sudo chown -Rh root:tomcat /opt/tomcat-base/conf /opt/tomcat-base/lib /opt/tomcat-base/bin

Make sure that conf files are readable by group. If not:

sudo chmod go+r /opt/tomcat-home/conf/* /opt/tomcat-base/conf/*

Change permissions on tomcat-users.xml so that others can’t read it:

sudo chmod 640 /opt/tomcat-home/conf/tomcat-users.xml /opt/tomcat-base/conf/tomcat-users.xml

Running Tomcat as a daemon

We need Tomcat to run as a daemon so that in case the server is rebooted, Tomcat starts automatically.

Daemon scripts should be created in /etc/init.d. So create a new script called tomcat8:

sudo vi /etc/init.d/tomcat8

For the contents of the daemon script, I copied the daemon script from the Tomcat 7 package in the Debian repositories. The end result is mostly a hack job where I updated paths for Java and Tomcat that I had installed in /opt. Here’s my script in full:

# /etc/init.d/tomcat8 -- startup script for the Tomcat 8 servlet engine
# Modified version of the tomcat7 script pulled from Debian Wheezy Tomcat 7 package
# Modifications are:
#   * Remove authbind.
#   * Remove JVM_TMP. We will use CATALINA_BASE/temp
#   * Explicitly set JAVA_HOME. No need to figure out where it is.
#   * Remove SECURITY. We are not using the Java security manager.
#   * Remove references to DEFAULT. We have no defaults to use.
#   * Explicitly provide values for variables that are supposed to be set
#     while installing the tomcat package.
#   * Remove references to POLICY_CACHE.
# Provides:          tomcat8
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Should-Start:      $named
# Should-Stop:       $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Tomcat.
# Description:       Start the Tomcat servlet engine.

set -e

DESC="Tomcat 8 servlet engine"

if [ `id -u` -ne 0 ]; then
	echo "You need root privileges to run this script"
	exit 1

# Make sure tomcat is started with system locale
if [ -r /etc/default/locale ]; then
	. /etc/default/locale
	export LANG

. /lib/lsb/init-functions

if [ -r /etc/default/rcS ]; then
	. /etc/default/rcS

# Run Tomcat 8 as this user ID and group ID

export JAVA_HOME=/opt/java8

# Directory where the Tomcat 8 binary distribution resides

# Directory for per-instance configuration files and webapps

# Default Java options
# Set java.awt.headless=true if JAVA_OPTS is not set so the
# Xalan XSL transformer can work without X11 display on JDK 1.4+
# It also looks like the default heap size of 64M is not enough for most cases
# so the maximum heap size is set to 128M
if [ -z "$JAVA_OPTS" ]; then
	JAVA_OPTS="-Djava.awt.headless=true -Xmx128M"

if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
	log_failure_msg "$NAME is not installed"
	exit 1

# pid file has to be in $CATALINA_BASE (or $CATALINA_HOME?)


# Look for Java Secure Sockets Extension (JSSE) JARs
if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then

catalina_sh() {
	# Escape any double quotes in the value of JAVA_OPTS
	JAVA_OPTS="$(echo $JAVA_OPTS | sed 's/\"/\\\"/g')"

	# Define the command to run Tomcat's as a daemon
	# set -a tells sh to export assigned variables to spawned shells.
		cd \"$CATALINA_BASE\"; \
		\"$CATALINA_SH\" $@"

	# Run the script as a daemon
	set +e
	touch "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
	chown $TOMCAT8_USER "$CATALINA_PID" "$CATALINA_BASE"/logs/catalina.out
	start-stop-daemon --start -b -u "$TOMCAT8_USER" -g "$TOMCAT8_GROUP" \
		-x /bin/bash -- -c "$TOMCAT_SH"
	set +a -e
	return $status

case "$1" in
	if [ -z "$JAVA_HOME" ]; then
		log_failure_msg "no JDK found - please set JAVA_HOME"
		exit 1

	if [ ! -d "$CATALINA_BASE/conf" ]; then
		log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
		exit 1

	log_daemon_msg "Starting $DESC" "$NAME"
	if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
		--user $TOMCAT8_USER --exec "$JAVA_HOME/bin/java" \
		>/dev/null; then

		catalina_sh start
		sleep 5
        	if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
			--user $TOMCAT8_USER --exec "$JAVA_HOME/bin/java" \
			>/dev/null; then
			if [ -f "$CATALINA_PID" ]; then
				rm -f "$CATALINA_PID"
			log_end_msg 1
			log_end_msg 0
	        log_progress_msg "(already running)"
		log_end_msg 0
	log_daemon_msg "Stopping $DESC" "$NAME"

	set +e
	if [ -f "$CATALINA_PID" ]; then
		start-stop-daemon --stop --pidfile "$CATALINA_PID" \
			--user "$TOMCAT8_USER" \
			--retry=TERM/20/KILL/5 >/dev/null
		if [ $? -eq 1 ]; then
			log_progress_msg "$DESC is not running but pid file exists, cleaning up"
		elif [ $? -eq 3 ]; then
			PID="`cat $CATALINA_PID`"
			log_failure_msg "Failed to stop $NAME (pid $PID)"
			exit 1
		rm -f "$CATALINA_PID"
		log_progress_msg "(not running)"
	log_end_msg 0
	set -e
	set +e
	start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
		--user $TOMCAT8_USER --exec "$JAVA_HOME/bin/java" \
		>/dev/null 2>&1
	if [ "$?" = "0" ]; then

		if [ -f "$CATALINA_PID" ]; then
		    log_success_msg "$DESC is not running, but pid file exists."
			exit 1
		    log_success_msg "$DESC is not running."
			exit 3
		log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
	set -e
	if [ -f "$CATALINA_PID" ]; then
		$0 stop
		sleep 1
	$0 start
        if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
		--user $TOMCAT8_USER --exec "$JAVA_HOME/bin/java" \
		>/dev/null; then
		$0 start
	log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
	exit 1

exit 0

Make the script executable and use the update-rc.d command to install the script as an init script. To start Tomcat 8 as a daemon use the invoke-rc.d command.

sudo chmod +x /etc/init.d/tomcat8
sudo update-rc.d tomcat8 defaults 92 08 >/dev/null
sudo invoke-rc.d tomcat8 start || true

Now you can start and stop the Tomcat daemon using these commands:

sudo service tomcat8 stop
sudo service tomcat8 start

If you had left the application directories in tomcat-base/webapps, just go to http://localhost:8080 and you should see the Tomcat welcome page:

Tomcat’s default home page

Installing Apache Portable Runtime (APR) for Tomcat

To get better performance, Tomcat documentation recommends that APR should be installed. This guide explains how to do that. Following that guide, this is what I ended up doing:

sudo apt-get install libapr1 libaprutil1 libapr1-dev libssl-dev make
export JAVA_HOME=/opt/java8
cd /opt/tomcat-home/temp/
tar zxvf ../bin/tomcat-native.tar.gz
cd tomcat-native-1.1.32-src/jni/native/
./configure --with-apr=/usr/bin/apr-1-config
sudo make install

sudo ln -s /usr/local/apr/lib/ /usr/lib/

Restart Tomcat and verify that it can find APR. The tomcat logs should show something like this:

Loaded APR based Apache Tomcat Native library 1.1.32 using APR version 1.5.1.

Next we will look at how to use a Apache HTTP server in front of Tomcat 8.

Comments (1)

1.  Saket Puranik Apr 23, 2015 04:52

Hi, I am using Redhat and it seems it does not support update-rc.d sudo: update-rc.d: command not found Regards Saket

Leave a Comment

HTML Syntax: Allowed