We develop locally using Eclipse and deploy to Tomcat 7 in AWS Elastic Beanstalk. Those who have already worked with AWS Elastic Beanstalk knows that once you deploy your WAR file, it will have not have a context path. For example, your web app’s root URL will look like http://webapp.com, instead of http://webapp.com/webapp/. Here we will mimic this setup on our local development environment. We have Apache running on port 80 and we want to keep it that way. We don’t want to change Tomcat to run on port 80.
1. Since we want to make our local look like production as much as possible, we will be using the URL http://local.webapp.com. Either configure local.webapp.com to point to 127.0.01 in your DNS provider, or just add 127.0.0.1 local.webapp.com to your hosts file. See %WINDIR%system32driversetchosts on Windows and /etc/hosts on Linux.
127.0.0.1 local.webapp.com
2. Edit Apache httpd.conf and enable mod_proxy and mod_proxy_http. On Apache 2.2, just uncomment these 2 lines.
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
3. Add the following at the end of the Apache httpd.conf file.
ProxyPass / http://local.webapp.com:8080/ ProxyPassReverse / http://local.webapp.com:8080/
You could also use an include file, instead of changing httpd.conf directly, for easier management. Create a file called conf/extra/webapp.conf under the Apache root directory, with the ProxyPass and ProxyPassReverse lines above. Then add this at the end of httpd.conf.
Include conf/extra/webapp.conf
4. Last piece of the puzzle is Tomcat. We remove the default context path and specify the proxy port. In Tomcat server.xml, change the context path from path=”webapp/” to “/”. If you run Tomcat from inside Eclipse, make sure you change that Tomcat install, which can be found under the Servers folder in Project Explorer. Then look for the Connector element with port=”8080″ and insert proxyPort=”80″. This tells Tomcat there’s a proxy in front of it.
... <Connector port="8080" proxyPort="80" ... /> ... <Engine> <Context path="/" ... /> </Engine>
5. That should be it. Restart Apache and Tomcat and you should be able to go to http://local.webapp.com and see your web application in action.
If you would like to setup SSL, then here are the extra steps you need to take.
1. Enable SSL on Apache by editing httpd.conf and uncommenting these two lines.
LoadModule ssl_module modules/mod_ssl.so Include conf/extra/httpd-ssl.conf
2. Install the certificate. You can use a real certificate or use a self signed one. How to get a certificate is out of scope for this post, but I’m sure there’s a lot of blog posts that can help you.
Once you have the certificate ready, rename the certificate to server.crt. If you got one, rename the intermediate certificate to server-ca.crt. If you got 2 intermediate certificates, combine them into one file. Also rename the private key used to generate the certificate to server.key. Place the renamed files server.crt, server-ca.crt and server.key in the Apache conf directory.
If you don’t like the idea of renaming your certificates, keep them as is and just make the filename changes inside httpd-ssl.conf.
3. In Tomcat server.xml, change the Connector element to use proxyPort=”443″ scheme=”https”, instead of the earlier proxyPort=”80″ change.
4. On 64-bit Windows, you might encounter the error:
SLSessionCache: Invalid argument: size has to be >= 8192 bytes
You can read more about this problem, and the solution, from the SSLSessionCache wiki page. If this is a local development environment, also try simply commenting out the SSLSessionCache and SSLSessionCacheTimeout lines in httpd-ssl.conf.
5. That’s it. Restart Tomcat and Apache and you should now be able to see your web application under https://local.webapp.com.
Here’s an extra tip. If you are running under Linux and want to block external access to port 8080, so you can only access your web application through Apache, you can run a few iptable commands. Here are the commands we use on Red Hat/CentOs.
iptables -A INPUT -p tcp -s IP_ADDRESS_HERE --dport 8080 -j ACCEPT iptables -A INPUT -p tcp --dport 8080 -j DROP service iptables save