Howto set up Tomcat 8 with Apache 2.4 and mod_jk on Ubuntu

Welcome,

In this walkthrough we will look at installing the binary distribution of Tomcat 8 on Ubuntu Server 14.04 LTS. Please note that we will not use Tomcat-native package here. Apache 2.4 will be used as a front optionally handling static content and ssl-termination while dynamic content will be served by the Tomcat-server through the Apache JServ Protocol (AJP 1.3) with apache module mod_jk.

apache_tomcat_setup

First we need to install a Java Runtime that the Tomcat-server will run in. I chose the server-jre8-version for obvious reason. The Server JRE is a runtime environment specifically targeted for deploying Java in server environments and it is available for 64-bit Linux, Solaris and Windows platforms. The Server JRE includes tools for JVM monitoring and tools commonly required for server applications, but does not include browser integration (the Java plug-in).

The Server JRE can be downloaded from this location: http://www.oracle.com/technetwork/java/javase/downloads/server-jre8-downloads-2133154.html

At the time of my download, this was the latest version available:

 server-jre-8u45-linux-x64.tar.gz

Download it to /usr/src/download or any other location you prefer and unpack.

root@ubuntu01:/usr/src/download# tar xvzf server-jre-8u45-linux-x64.tar.gz

That will create the folder /usr/src/download/jdk1.8.0_45

Change the owner recursively on that folder, I’m using root as user and group here.

root@ubuntu01:/usr/src/download# chown -R root:root jdk1.8.0_45/

Move the folder to your desired location, I chose /opt here since that folder is typically for third-party add-on software.

root@ubuntu01:/usr/src/download# mv jdk1.8.0_45/ /opt

To make it obvious that this is the Server JRE I created a symlink pointing to that folder.

root@ubuntu01:/opt# ln -s jdk1.8.0_45/ server_jre

root@ubuntu01:/opt# ls -al
drwxr-xr-x  8 root   root     4096 Apr 10 19:22 jdk1.8.0_45
lrwxrwxrwx  1 root   root       12 Jul  1 11:18 server_jre -> jdk1.8.0_45/

Just to verify this is the correct java version

root@ubuntu01:/opt/server_jre/bin# ./java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

That’s all for the Java installation, now let’s download and install Tomcat.

Tomcat installation:

Download Tomcat binary distribution:

root@ubuntu01:/usr/src/download# wget http://apache.mirrors.spacedump.net/tomcat/tomcat-8/v8.0.23/bin/apache-tomcat-8.0.23.tar.gz

Unpack

root@ubuntu01:/usr/src/download# tar xvzf apache-tomcat-8.0.23.tar.gz

Move to /opt

root@ubuntu01:/usr/src/download# mv apache-tomcat-8.0.23 /opt/

create symlink in /opt folder

root@ubuntu01:/usr/src/download# cd /opt/
root@ubuntu01:/opt# ln -s apache-tomcat-8.0.23/ tomcat

For security purposes, Tomcat should be run as an unprivileged user. We will create a new user (tomcat) and group (tomcat) that will run the Tomcat-service.

root@ubuntu01:/opt# groupadd tomcat

Then create a new tomcat user. We’ll make this user a member of the tomcat group, with a home directory of /opt/tomcat, and with a shell of /bin/false

root@ubuntu01:/opt# useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat

Change to the new user and group recursively on the tomcat folder structure

root@ubuntu01:/opt# chown -R tomcat:tomcat apache-tomcat-8.0.23

Now it should look like this when listing the /opt folder:

root@ubuntu01:/opt# ls -al
drwxr-xr-x  9 tomcat tomcat  apache-tomcat-8.0.23
drwxr-xr-x  8 root   root    jdk1.8.0_45
lrwxrwxrwx  1 root   root    server_jre -> jdk1.8.0_45/
lrwxrwxrwx  1 root   root    tomcat -> apache-tomcat-8.0.23/

Now, comment out the port 8080 connector in server.xml…(we will only enable AJP on port 8009)

root@ubuntu01:/opt# cd tomcat/conf/
root@ubuntu01:/opt/tomcat/conf# vi server.xml
<!-- <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> -->

Make sure the ajp-connector is not disabled…

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Configure Tomcat Web Management Interface. Put this in your tomcat-users.xml in between the <tomcat-users> tags, choose your username and password.

root@ubuntu01:/opt/tomcat/conf# vi tomcat-users.xml
  <role rolename="manager-gui"/>
  <user username="admin" password="password" roles="manager-gui"/>

Because we want to be able to run Tomcat as a service, we will set up an Upstart script. Create and install a Tomcat Upstart script:

root@ubuntu01:/opt/tomcat/conf# vi /etc/init/tomcat.conf

Put this content in the new file:

description "Tomcat Server"

start on runlevel [2345]
stop on runlevel [!2345]
respawn
respawn limit 10 5

setuid tomcat
setgid tomcat

env JAVA_HOME=/opt/server_jre
env CATALINA_HOME=/opt/tomcat

# Modify these options as needed
env JAVA_OPTS="-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"
env CATALINA_OPTS="-Xms512M -Xmx1024M -server -XX:+UseParallelGC"

exec $CATALINA_HOME/bin/catalina.sh run

# cleanup temp directory after stop
post-stop script
  rm -rf $CATALINA_HOME/temp/*
end script

Tomcat can now be started/stopped by the service command. It will also startup automatically on boot.

root@ubuntu01:/opt/tomcat/conf# service tomcat start
tomcat start/running, process 5666

The log file is located at /var/log/upstart/tomcat.log

root@ubuntu01:/var/log/upstart# tail tomcat.log

Looking at the log file after startup…

tomcat_upstart_log

…we can see the following message in the log output:

org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

Ignore this message. The library referred to is bundled into an OS specific libtcnative.so (or dll for windows) loaded via JNI. It allows Tomcat to use OS functionalities not provided in the Java Runtime (such as sendfile, epoll, OpenSSL, OS level functionality (random number generation, system status, etc), and native process handling (shared memory, NT pipes and Unix sockets). Tomcat will run just fine without it, these features allows making Tomcat a general purpose webserver. We will however only use Tomcat as a backend-server working together with the Apache-webserver, hence we ignore this message.

Installing and configuring mod_jk

root@ubuntu01:/var/log/upstart# apt-get install libapache2-mod-jk

Preparing to unpack .../libapache2-mod-jk_1%3a1.2.37-3_amd64.deb ...
Unpacking libapache2-mod-jk (1:1.2.37-3) ...
Setting up libapache2-mod-jk (1:1.2.37-3) ...
apache2_invoke: Enable module jk
 * Restarting web server apache2

Now with the following command we can see that the module jk_module has indeed been loaded.

root@ubuntu01:/var/log/upstart# apache2ctl -M

Loaded Modules:
 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 log_config_module (static)
 logio_module (static)
 version_module (static)
 unixd_module (static)
 access_compat_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 authn_core_module (shared)
 authn_file_module (shared)
 authz_core_module (shared)
 authz_host_module (shared)
 authz_user_module (shared)
 autoindex_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 filter_module (shared)
 jk_module (shared)
 mime_module (shared)
 mpm_prefork_module (shared)
 negotiation_module (shared)
 php5_module (shared)
 rewrite_module (shared)
 setenvif_module (shared)
 status_module (shared)

In the jk.conf file we can see where the workers.properties file is located:

root@ubuntu01:/var/log/upstart# cd /etc/apache2/mods-available/
root@ubuntu01:/etc/apache2/mods-available# more jk.conf

# Configuration Example for mod_jk
# used in combination with Apache 2.2.x

<IfModule jk_module>

    # We need a workers file exactly once
    # and in the global server
    JkWorkersFile /etc/libapache2-mod-jk/workers.properties

    # Our JK error log
    # You can (and should) use rotatelogs here
    JkLogFile /var/log/apache2/mod_jk.log

    # Our JK log level (trace,debug,info,warn,error)
    JkLogLevel info

    # Our JK shared memory file
    JkShmFile /var/log/apache2/jk-runtime-status

…we can see that the workers.properties is located under /etc/libapache2-mod-jk

Edit the workers.properties file, put in your path to your tomcat_home and java_home:

#
# workers.tomcat_home should point to the location where you
# installed tomcat. This is where you have your conf, webapps and lib
# directories.
#
workers.tomcat_home=/opt/tomcat

#
# workers.java_home should point to your Java installation. Normally
# you should have a bin and lib directories beneath it.
#
workers.java_home=/opt/server_jre

Make sure the other settings are correctly put in here, should look similar to this:

worker.list=ajp13_worker
worker.ajp13_worker.port=8009
worker.ajp13_worker.host=localhost
worker.ajp13_worker.type=ajp13
worker.ajp13_worker.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=ajp13_worker

Finally to configure the URLs that Apache should pass through the Tomcat, edit your VirtualHost directive:

root@ubuntu01:/etc/libapache2-mod-jk# cd /etc/apache2/sites-available/
root@ubuntu01:/etc/apache2/sites-available# vi vhosts-default.conf
<VirtualHost *:80>
        ServerName www.example.com
        DocumentRoot /var/www/example
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        <Directory /var/www/example>
                Options Indexes FollowSymLinks
                AllowOverride None
                Require all granted
        </Directory>
        JkMount /manager/* ajp13_worker
        JkMount /manager ajp13_worker
        JkMount /examples/* ajp13_worker
        JkMount /examples ajp13_worker
</VirtualHost>

As you can see we are using the www.example.com domain here just for instructional purpose. Since I’m not the owner of that domain and cannot make any DNS-configuration, such as adding an A-record, for that domain I will put in an entry into my client computer host file just to get this example working. The document root I set to /var/www/example so let’s create that folder first. That location is where any static content optionally will be placed if any, it depends on how you do your jkmount-mappings above. As we can see anything with /manager or /examples will be mapped to Tomcat and the rest will be searched for, by Apache, in the /var/www/example folder.

root@ubuntu01:/var/www# mkdir example

In the client machine I now temporarily set a record to map the url www.example.com to my servers ip-address. I’m using a windows client machine here and editing the hosts-file in notepad as Administrator (right-click-> Run as Administrator). Windows will first look in the host-file and then resolve names with DNS which is exactly the order of precedence we want here in order for this example to work.

C:\Windows\System32\drivers\etc\hosts
85.225.140.7  www.example.com

After a reload of Apache…

root@ubuntu01:/etc/apache2/sites-available# service apache2 reload

We can now point the browser on the windows client machine to try out if everything works:

tomcat_examples

The Tomcat examples webapp is indeed working. Now trying /manager…

tomcat_manager_auth_required

After login with your admin/password this is what welcomes you…

tomcat_manager

That is all for now. Everything works as expected. Please consider if you really want the /manager mappings to be enabled all of the time. For security reasons I prefer to enable that mapping only when I have to do some deployment. Keep in mind that any password sent over http is sent “in the clear” for any eavesdropper to pick up, you better use https in that case. I will later blog about setting up SSL using SNI with Apache. Edit! Now available here: http://www.creang.com/howtoforge/setting_up_sni_with_apache_2_4/

2 thoughts on “Howto set up Tomcat 8 with Apache 2.4 and mod_jk on Ubuntu”

Leave a Reply

Your email address will not be published. Required fields are marked *