Tutorial

How To Encrypt Tomcat 8 Connections with Apache or Nginx on Ubuntu 16.04

How To Encrypt Tomcat 8 Connections with Apache or Nginx on Ubuntu 16.04

Introduction

Apache Tomcat is a web server and servlet container designed to serve Java applications. Frequently used in production enterprise deployments and for smaller application needs, Tomcat is both flexible and powerful.

In this guide, we will discuss how to secure your Ubuntu 16.04 Tomcat installation with SSL. By default, upon installation, all communication between the Tomcat server and clients is unencrypted, including any passwords entered or any sensitive data. There are a number of ways that we can incorporate SSL into our Tomcat installation. This guide will cover how to set up a SSL-enabled proxy server to securely negotiate with clients and then hand requests off to Tomcat.

We will cover how to set this up with both Apache and Nginx.

Why a Reverse Proxy?

There are a number of ways that you can set up SSL for a Tomcat installation, each with its set of trade-offs. After learning that Tomcat has the ability to encrypt connections natively, it might seem strange that we’d discuss a reverse proxy solution.

SSL with Tomcat has a number of drawbacks that make it difficult to manage:

  • Tomcat, when run as recommended with an unprivileged user, cannot bind to restricted ports like the conventional SSL port 443: There are workarounds to this, like using the authbind program to map an unprivileged program with a restricted port, setting up port forwarding with a firewall, etc., but they still represent additional complexity.
  • SSL with Tomcat is not as widely supported by other software: Projects like Let’s Encrypt provide no native way of interacting with Tomcat. Furthermore, the Java keystore format requires conventional certificates to be converted before use, which complicates automation.
  • Conventional web servers release more frequently than Tomcat: This can have significant security implications for your applications. For instance, the supported Tomcat SSL cipher suite can become out-of-date quickly, leaving your applications with suboptimal protection. In the event that security updates are needed, it is likely easier to update a web server than your Tomcat installation.

A reverse proxy solution bypasses many of these issues by simply putting a strong web server in front of the Tomcat installation. The web server can handle client requests with SSL, functionality it is specifically designed to handle. It can then proxy requests to Tomcat running in its normal, unprivileged configuration.

This separation of concerns simplifies the configuration, even if it does mean running an additional piece of software.

Prerequisites

In order to complete this guide, you will have to have Tomcat already set up on your server. This guide will assume that you used the instructions in our Tomcat 8 on Ubuntu 16.04 installation guide to get set up.

When you have a Tomcat up and running, continue below with the section for your preferred web server. Apache starts directly below, while the Nginx configuration can be found by skipping ahead a bit.

(Option 1) Proxying with the Apache Web Server’s mod_jk

The Apache web server has a module called mod_jk which can communicate directly with Tomcat using the Apache JServ Protocol. A connector for this protocol is enabled by default within Tomcat, so Tomcat is already ready to handle these requests.

Section Prerequisites

Before we can discuss how to proxy Apache web server connections to Tomcat, you must install and secure an Apache web server.

You can install the Apache web server by following step 1 of this guide. Do not install MySQL or PHP.

Afterwards, you will need to set up SSL on the server. The way you do this will depend on whether you have a domain name or not.

  • If you have a domain name… the easiest way to secure your server is with Let’s Encrypt, which provides free, trusted certificates. Follow our Let’s Encrypt guide for Apache to set this up.
  • If you do not have a domain… and you are just using this configuration for testing or personal use, you can use a self-signed certificate instead. This provides the same type of encryption, but without domain validation. Follow our self-signed SSL guide for Apache to get set up.

When you are finished with these steps, continue below to learn how to hook up the Apache web server to your Tomcat installation.

Step 1: Install and Configure mod_jk

First, we need to install the mod_jk module. The Apache web server uses this to communicate with Tomcat using the Apache JServ Protocol.

We can install mod_jk from Ubuntu’s default repositories. Update the local package index and install by typing:

  1. sudo apt-get update
  2. sudo apt-get install libapache2-mod-jk

The module will be enabled automatically upon installation.

Next, we need to configure the module. The main configuration file is located at /etc/libapache2-mod-jk/workers.properties. Open this file now in your text editor:

  1. sudo nano /etc/libapache2-mod-jk/workers.properties

Inside, find the workers.tomcat_home directive. Set this to your Tomcat installation home directory. For our Tomcat installation, that would be /opt/tomcat:

/etc/libapache2-mod-jk/workers.properties
workers.tomcat_home=/opt/tomcat

Save and close the file when you are finished.

Step 2: Adjust the Apache Virtual Host to Proxy with mod_jk

Next, we need to adjust our Apache Virtual Host to proxy requests to our Tomcat installation.

The correct Virtual Host file to open will depend on which method you used to set up SSL.

If you set up a self-signed SSL certificate using the guide linked to above, open the default-ssl.conf file:

  1. sudo nano /etc/apache2/sites-available/default-ssl.conf

If you set up SSL with Let’s Encrypt, the file location will depend on what options you selected during the certificate process. You can find which Virtual Hosts are involved in serving SSL requests by typing:

  1. sudo apache2ctl -S

Your output will likely begin with something like this:

  1. Output
    VirtualHost configuration:
  2. *:80 example.com (/etc/apache2/sites-enabled/000-default.conf:1)
  3. *:443 is a NameVirtualHost
  4. default server example.com (/etc/apache2/sites-enabled/000-default-le-ssl.conf:2)
  5. port 443 namevhost example.com (/etc/apache2/sites-enabled/000-default-le-ssl.conf:2)
  6. port 443 namevhost www.example.com (/etc/apache2/sites-enabled/default-ssl.conf:2)
  7. . . .

Looking at the lines associated with SSL port 443 (lines 3-6 in this example), we can determine which Virtual Hosts files are involved in serving those domains. Here, we see that both the 000-default-le-ssl.conf file and the default-ssl.conf file are involved, so you should edit both of these. Your results will likely differ:

  1. sudo nano /etc/apache2/sites-enabled/000-default-le-ssl.conf
  2. sudo nano /etc/apache2/sites-enabled/default-ssl.conf

Regardless of which files you have to open, the procedure will be the same. Somewhere within the VirtualHost tags, you should enter the following:

<VirtualHost *:443>

	. . .

	JKMount /* ajp13_worker

	. . .

</VirtualHost>

Save and close the file. Repeat the above process for any other files you identified that need to be edited.

When you are finished, check your configuration by typing:

  1. sudo apache2ctl configtest

If the output contains Syntax OK, restart the Apache web server process:

  1. sudo systemctl restart apache2

You should now be able get to your Tomcat installation by visiting the SSL version of your site in your web browser:

https://example.com

Next, skip past the Nginx configuration below and continue at the section detailing how to restrict access to Tomcat in order to complete your configuration.

(Option 2) HTTP Proxying with Nginx

Proxying is also easy with Nginx, if you prefer it to the Apache web server. While Nginx does not have a module allowing it to speak the Apache JServ Protocol, it can use its robust HTTP proxying capabilities to communicate with Tomcat.

Section Prerequisites

Before we can discuss how to proxy Nginx connections to Tomcat, you must install and secure Nginx.

You can install Nginx by following our guide on installing Nginx on Ubuntu 16.04.

Afterwards, you will need to set up SSL on the server. The way you do this will depend on whether you have a domain name or not.

  • If you have a domain name… the easiest way to secure your server is with Let’s Encrypt, which provides free, trusted certificates. Follow our Let’s Encrypt guide for Nginx to set this up.
  • If you do not have a domain… and you are just using this configuration for testing or personal use, you can use a self-signed certificate instead. This provides the same type of encryption, but without domain validation. Follow our self-signed SSL guide for Nginx to get set up.

When you are finished with these steps, continue below to learn how to hook up the Nginx web server to your Tomcat installation.

Step 1: Adjusting the Nginx Server Block Configuration

Setting up Nginx to proxy to Tomcat is very straight forward.

Begin by opening the server block file associated with your site. We will assume you are using the default server block file in this guide:

  1. sudo nano /etc/nginx/sites-available/default

Inside, towards the top of the file, we need to add an upstream block. This will outline the connection details so that Nginx knows where our Tomcat server is listening. Place this outside of any of the server blocks defined within the file:

/etc/nginx/sites-available/default
upstream tomcat {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {

	. . .

Next, within the server block defined for port 443, modify the location / block. We want to pass all requests directly to the upstream block we just defined. Comment out the current contents and use the proxy_pass directive to pass to the “tomcat” upstream we just defined.

We will also need to include the proxy_params configuration within this block. This file defines many of the details of how Nginx will proxy the connection:

/etc/nginx/sites-available/default
upstream tomcat {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    . . .

    location / {
        #try_files $uri $uri/ =404;
        include proxy_params;
        proxy_pass http://tomcat/;
    }

    . . .
}

When you are finished, save and close the file.

Step 2: Test and Restart Nginx

Next, test to make sure your configuration changes did not introduce any syntax errors:

  1. sudo nginx -t

If no errors are reported, restart Nginx to implement your changes:

  1. sudo systemctl restart nginx

You should now be able get to your Tomcat installation by visiting the SSL version of your site in your web browser:

https://example.com

Restricting Access to the Tomcat Installation

Now you have SSL encrypted access to your Tomcat installation, we can lock down the Tomcat installation a bit more.

Since we want all of our requests to Tomcat to come through our proxy, we can configure Tomcat to only listen for connections on the local loopback interface. This ensures that outside parties cannot attempt to make requests from Tomcat directly.

Open the server.xml file within your Tomcat configuration directory to change these settings:

  1. sudo nano /opt/tomcat/conf/server.xml

Within this file, we need to modify the Connector definitions. Currently there are two Connectors enabled within the configuration. One handles normal HTTP requests on port 8080, while the other handles Apache JServ Protocol requests on port 8009. The configuration will look something like this:

/opt/tomcat/conf/server.xml
. . .

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
. . .

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

In order to restrict access to the local loopback interface, we just need to add an “address” attribute set to 127.0.0.1 in each of these Connector definitions. The end result will look like this:

/opt/tomcat/conf/server.xml
. . .

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               address="127.0.0.1"
               redirectPort="8443" />
. . .

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

After you’ve made those two changes, save and close the file.

We need to restart our Tomcat process to implement these changes:

  1. sudo systemctl restart tomcat

If you followed our Tomcat installation guide, you have a ufw firewall enabled on your installation. Now that all of our requests to Tomcat are restricted to the local loopback interface, we can remove the rule from our firewall that allowed external requests to Tomcat.

  1. sudo ufw delete allow 8080

Your Tomcat installation should now only be accessible through your web server proxy.

Conclusion

At this point, connections to your Tomcat instance should be encrypted with SSL with the help of a web server proxy. While configuring a separate web server process might increase the software involved in serving your applications, it simplifies the process of securing your traffic significantly.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

How can I use apache2 like phpMyadmin?

Hey Justin,

Thanks for the great tutorial! I spotted a error and typo at the upstream tomcat block.

127.0.0.1:8080 fail_timout=0; should be server 127.0.0.1:8080 fail_timeout=0;

One thing that you may want to add to the guide above is to have users run $netstat -ln to confirm that the AJP listener is alive on port 8009. I believe the package ‘tomcat8-admin’ package enables it by default.

I didn’t install that package, so I enabled the listener by un-commenting <Connector port=“8009” protocol=“AJP/1.3” redirectPort=“8443” /> in /etc/tomcat8/server.xml and then restarting tomcat8

By the way, this is good technical writing. It nicely anticipates the reader’s context so the information given is the appropriate level of detail. Nice work.

For spiders :

This will fix the error in /var/log/apachet2/mod_jk.log : (ajp13_worker) Failed opening socket to (::1:8009) (errno=111)

“Service Unavailable The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.”

I cannot thank you enough for this excellent and wonderful guide! Brilliant!

Thanx Justin. I’ve been sitting for 2 days straight trying to figure out the SSL config for Tomcat 8. The reference guide at apache is ****. This approach took less than an hour an know I have a secure connection to my Tomcat. So thanx to you I’m only 2, and thank God not 2++, days behind schedule :D

Hello,

In Section Prerequisites, you said that DO NOT install PHP and MySQL.

How can I secure install them with encrypt connection after this ?

Thanks so much.

Hello Justin! I appreciate for your tutorials. Great!

I finished this tutorial with all prerequisites. Main tomcat page opens via https. But:

  1. i got Access Denied (403) at url https://my_domain.com/manager/html.

along with:

  1. http://127.0.0.1:8080/manager/html - available and shows Main tomcat page.
  2. http://127.0.0.1/ - available and shows Apache2 default page.

Thank you!

This tutorial helped me encrypt Tomcat 8 connections with Apache 2.4 on Ubuntu 16.04.

However, one of the problems I had was that Websocket doesn’t work over mod_jk. As a result, the WebSocket examples on Tomcat home page didn’t work (ex: localhost:8080/examples/websocket/chat.xhtml) after editing server.xml (i.e., adding address=“127.0.0.1”) to restrict access to the tomcat installation.

I ended up enabling mod_proxy_wstunnel and modifying my virtualhost files to make Apache also proxy the WebSockets.

Now I have Apache reverse proxy Tomcat connection with WebSocket on https! Yay!

Hi, Nice tutorial!

I have few questions:

  1. Is it possible to open tomcat at : https://example.com/tomcat ? ( without broken links - the links in the tomcat page to point to https://example.com/manager/html but the address to be https://example.com/tomcat/manager/html

2)if I want to have this structure: https://example.com/ - static site nginx https://example.com/tomcat - tomcat manger (with working links) https://example.com/app - tomcat app (deployed at /app on tomcat)

What configuration should I use?

Thank you!

Everything works until the last step, which is to change the HTTP and AJP Connectors in server.xml to only listen on localhost. Here’s the change I made to the AJP Connector:

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

Before this change, typing https://myhostname takes me to the Tomcat administration page; after it, I get “503 Service Unavailable”.

Here’s the relevant portion of mod_jk.log

[info] jk_open_socket::jk_connect.c (817): connect to ::1:8009 failed (errno=111)
[Thu Mar 23 17:37:13.808 2017] [14484:140252643563264] [info] ajp_connect_to_endpoint::jk_ajp_common.c (1068): (ajp13_worker) Failed opening socket to (::1:8009) (errno=111)
[Thu Mar 23 17:37:13.808 2017] [14484:140252643563264] [error] ajp_send_request::jk_ajp_common.c (1728): (ajp13_worker) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=111)

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.