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
:
PATH="/opt/java8/bin:$PATH"
Installing Tomcat 8
Download the latest Tomcat 8 from here. Extract to /opt
:
cd /opt
sudo wget http://psg.mtu.edu/pub/apache/tomcat/tomcat-8/v8.0.15/bin/apache-tomcat-8.0.15.tar.gz
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 \
"tomcat"
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:
#!/bin/sh
#
# /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.
#
### BEGIN INIT INFO
# 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.
### END INIT INFO
set -e
PATH=/bin:/usr/bin:/sbin:/usr/sbin
NAME=tomcat8
DESC="Tomcat 8 servlet engine"
if [ `id -u` -ne 0 ]; then
echo "You need root privileges to run this script"
exit 1
fi
# Make sure tomcat is started with system locale
if [ -r /etc/default/locale ]; then
. /etc/default/locale
export LANG
fi
. /lib/lsb/init-functions
if [ -r /etc/default/rcS ]; then
. /etc/default/rcS
fi
# Run Tomcat 8 as this user ID and group ID
TOMCAT8_USER=tomcat
TOMCAT8_GROUP=tomcat
export JAVA_HOME=/opt/java8
# Directory where the Tomcat 8 binary distribution resides
CATALINA_HOME=/opt/tomcat-home
# Directory for per-instance configuration files and webapps
CATALINA_BASE=/opt/tomcat-base
# 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"
fi
if [ ! -f "$CATALINA_HOME/bin/bootstrap.jar" ]; then
log_failure_msg "$NAME is not installed"
exit 1
fi
# pid file has to be in $CATALINA_BASE (or $CATALINA_HOME?)
CATALINA_PID="$CATALINA_BASE/tomcat.pid"
CATALINA_SH="$CATALINA_HOME/bin/catalina.sh"
CATALINA_TMPDIR="$CATALINA_BASE/temp"
# Look for Java Secure Sockets Extension (JSSE) JARs
if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then
JSSE_HOME="${JAVA_HOME}/jre/"
fi
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 catalina.sh as a daemon
# set -a tells sh to export assigned variables to spawned shells.
TOMCAT_SH="set -a; JAVA_HOME=\"$JAVA_HOME\"; \
CATALINA_HOME=\"$CATALINA_HOME\"; \
CATALINA_BASE=\"$CATALINA_BASE\"; \
JAVA_OPTS=\"$JAVA_OPTS\"; \
CATALINA_PID=\"$CATALINA_PID\"; \
CATALINA_TMPDIR=\"$CATALINA_TMPDIR\"; \
LANG=\"$LANG\"; JSSE_HOME=\"$JSSE_HOME\"; \
cd \"$CATALINA_BASE\"; \
\"$CATALINA_SH\" $@"
# Run the catalina.sh 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" \
-c "$TOMCAT8_USER" -d "$CATALINA_TMPDIR" -p "$CATALINA_PID" \
-x /bin/bash -- -c "$TOMCAT_SH"
status="$?"
set +a -e
return $status
}
case "$1" in
start)
if [ -z "$JAVA_HOME" ]; then
log_failure_msg "no JDK found - please set JAVA_HOME"
exit 1
fi
if [ ! -d "$CATALINA_BASE/conf" ]; then
log_failure_msg "invalid CATALINA_BASE: $CATALINA_BASE"
exit 1
fi
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"
fi
log_end_msg 1
else
log_end_msg 0
fi
else
log_progress_msg "(already running)"
log_end_msg 0
fi
;;
stop)
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
fi
rm -f "$CATALINA_PID"
else
log_progress_msg "(not running)"
fi
log_end_msg 0
set -e
;;
status)
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
else
log_success_msg "$DESC is not running."
exit 3
fi
else
log_success_msg "$DESC is running with pid `cat $CATALINA_PID`"
fi
set -e
;;
restart|force-reload)
if [ -f "$CATALINA_PID" ]; then
$0 stop
sleep 1
fi
$0 start
;;
try-restart)
if start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
--user $TOMCAT8_USER --exec "$JAVA_HOME/bin/java" \
>/dev/null; then
$0 start
fi
;;
*)
log_success_msg "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
exit 1
;;
esac
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:
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
make
sudo make install
sudo ln -s /usr/local/apr/lib/libtcnative-1.so /usr/lib/libtcnative-1.so
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.