For the last 8 years or so, I have almost exclusively developed applications that run on Tomcat. Whether it be JSP applications, servlet based SOAP/XML services, Struts, Faces, or Axis 2 web services - Tomcat has always been involved. As such, many, many times over that period, I have also been asked to setup servers in the work environment, or hosted servers for clients, or install complete systems onto developer machines and laptops.
Tomcat is easy to setup. However, Tomcat on its own does often not provide everything that is needed for a production environment. Tomcat is wonderful at running Java servlet based applications. When a client needs to have multiple Tomcats on one server/environment, all going through the same external port and all using the same SSL certificate, the excellent Apache HTTP Server is also needed. Every single time I need to set up a secure Apache proxy, that redirects to internal Tomcats based on the context of an incoming request, I have to spend ages playing around with conf files to get it to work. I can never remember quite how to do it.
This blog is a guide to setting up Apache as a secured, external, proxy to multiple internal Tomcats, where Tomcat resolution is managed via the context names in the URL. The advantages of this approach are that you do not need domain names for your forwarding, you only need one SSL certificate for the server, and you only need one external port (443) opened on your server.
The architecture is pretty simple, and is illustrated in the following diagram (drawn in the NetBeans UML editor which is handy but has been hit with the ugly stick):
Installing Apache 2.2
Apache 2.2 is available from the Apache Software Foundation, here. Download the Win 32 binary, with Open SSL support included. Note that this guide will work for non Win servers also, however, the initial install on those boxes can be tough, so I'm not wasting time here explaining it.
Run the installer, setup your domain and server name details. You will be wanting to configure Apache to install as a Windows service so that it is always available. Once it is installed, open up a web browser and go to http://localhost - you will see the welcome screen containing the text "It works!".
Lock it down!
The version of Apache downloaded above contains all that is necessary to secure it to run over SSL/HTTPS. Open a command prompt and go to the Apache bin folder C:\Program Files\Apache Software Foundation\Apache2.2\bin. Enter the following command to generate a self-signed certificate:
OPENSSL.exe req -new -x509 -nodes -extensions v3_req
-days 365 -config ..\conf\openssl.cnf -out ..\conf\server.crt
The common name is your domain name (e.g. www.google.com), if you have one. This will generate a key file, server.key, and a certificate file, server.crt. The certificate is for external applications to send encrypted traffic to the Apache server. The key is what the Apache server uses to decrypt that traffic.
Configuring Apache Httpd
Now that the SSL parts are generated, the final step is to configure the Apache server to be secure and to act as a proxy to our Tomcat(s). The file conf\httpd.conf contains most of the configuration for the Apache server.
The following changes need to be applied to it:
- Uncomment the proxy_module, proxy_http_module and ssl_module modules.
- Uncomment the include statement for conf/extra/httpd-ssl.conf.
- Edit conf/extra/httpd-ssl.conf and include lines similar to the following before the closing VirtualHost tag:
ProxyPass /context-name-1 http://localhost:8080/context-name-1
ProxyPassReverse /context-name-1 http://localhost:8080/context-name-1
ProxyPass /context-name-2 http://localhost:8080/context-name-2
ProxyPassReverse /context-name-2 http://localhost:8080/context-name-2
ProxyPass /context-name-3 http://localhost:8081/context-name-3
ProxyPassReverse /context-name-3 http://localhost:8081/context-name-3
These setup the name based proxy - so anything coming into the server with a context name of context-name-1 will go to the Tomcat on port 8080 and to the webapp named context-name-1.
Note that the above setup will also have setup an unsecured Apache listener on port 80 also - this can be turned off if all traffic is going to port 443.
Now go to the tray icons on your desktop, open the Apache Service Monitor, and hit restart. Its done!
If you get any errors, simply check the log files under the logs folder (error.log).
Tomcat Proxy Settings
If you are serving up a service then you are all done. If you are also or only serving web pages, then you need to also tell your Tomcat the domain details and that it is a proxy server. If you don't, you will find that all the links on your rendered JSP pages actually contain the local tomcat protocol (HTTP), host (localhost) and port (e.g. 8080), instead of your secured domain.
Luckily, Tomcat supports this through its Connector element (which is found in conf/server.xml in your Tomcat CATALINA_BASE folder). Set the following parameters to similar values to match your domain or external IP address (if you have no domain):
- secure = false
- scheme = https
- proxyName = www.mydomain.com
- proxyPort = 443
This will force Tomcat to translate all the link addresses to match your domain details. Note that secure is set to false, because the Tomcat is not handling SSL. However, the scheme must be set to HTTPS so that all the links on your pages contain that as their protocol.