Recent Posts

RSS Feeds

Non-root Tomcat on Port 80 on a VPS without Apache

Java web applications typically run an platform consisting of Linux, Apache, MySQL, Tomcat and Java. In memory constrained systems like virtual private servers (VPS) you may get rid of the Apache web server to save memory and gain speed. The idea sounds simple: configure Tomcat for Port 80 and start it instead of Apache but in practice there are many traps on the way. And the special nature of VPS adds to them generously.

Non-root Tomcat doesn't start on port 80 

For security reasons only applications (daemons, servives) running with root privileges may listen on ports <1024 and port 80 is one of them. And for the same security reasons Tomcat shouldn't be run with root privileges but as the tomcat user. Therefore Tomcat may not listen to port 80 (directly).

Possible memory savings by replacing Apache web server

If your Apache web server is only responsible for the port 80->8080 mapping via mod_ajp or mod_proxy you may replace it and save some memory. In my case there was on Apache server process running as user 'root' and two slaves running as user 'www-data'. All three processes reported the usage of 11 MB main memory, but they shared some of it. So the benefit lies somewhere between 11 and 33 MB. The difference in memory usage measured with Apache started and stopped showed a real memory usage of 15 MB. This is a small saving on a 1 GB root server, but may be the solution to run your java web application on a VPS with only 256MB, where half of it is already used by OS and system daemons. The amount of memory saved differs in magnitude depending an the modules that are included in every apache server process, e.g. mod-php5, mod-perl, etc. so please evalute it yourself.

Redirection of Port 80 via Iptables on a VPS

The standard solution if you google for it is to redirect all requests on port 80 to port 8080 via the iptables subsystem of the Linux kernel. Since this just replaces the port information in the TCP paket in-place instead of copying the content to a new paket in a user process (Apache) this happens really fast. Tomcat may listen via its http connector Catalina on port 8080 as usual and does not see the difference.

The most important difference between a root server and a VPS is that you as root may do anything with one exception on a VPS: you may not change the kernel or load any modules. Since the Iptables subsystem is a part of the kernel you are totally depending on your provider if it is available and to what extend.

So I tried my luck on my VPS with Linux kernel version "2.6.18-028stab057.4 (root@rhel5-64-build)" and iptables version "1.3.6" on a Debian 4 installation. The OpenVZ/Virtuozzo Version is not known to me but /proc/user_beancounters says "2.5" in the first line.

The iptables rule in /etc/iptables.conf should have been:

# NAT for Tomcat without Apache
*nat
:PREROUTING ACCEPT
:POSTROUTING ACCEPT
:OUTPUT ACCEPT
-A PREROUTING --src 0/0 --dst <your_ip> -p tcp --dport 80 -j REDIRECT --to-p
orts 8080
COMMIT

But this gave me an error message. The special build-in target of "REDIRECT" does not exist in the kernel which my provider uses. After some more googling around I came over an alternative method using the target "DNAT". I replaced the line from above with this one:

-A PREROUTING --src 0/0 --dst <your_ip> -p tcp -m tcp --dport 80 -j DNAT --to-destination <your_ip>:8080

Now a /etc/init.d/iptables stop followed by /etc/init.d/iptables start accepted my redirection/dnat rule. But Tomcat didn't answer. The reason was my firewall settings blocked requests on port 8080 so I opened that one too. In the rules of the filter chain I added:

# allow direct http to Tomcat Catalina
-A INPUT -p tcp --dport 8080 -j ACCEPT

I tried to call my Java web application on Tomcat but Tomcat said it didn't know the host I requested. With Apache web server as reverse proxy the only host that was called on Tomcat was 'localhost'. The virtual hosting was all configured in the Apache configuration files. Now I had to set up Tomcat for virtual hosting according to some Howto like this one "Virtual Hosting with Tomcat". The main trick is to define additional <Host> elements in the server.xml for every domain. You may skip some additional elements if you declare some domains as <Alias> entries of others. See the offical Tomcat doc on this.

Configure a proxy connector for Tomcat

After configuring all domains as virtual hosts with minimum web applications even for static HTML content all URLs are answered by Tomcat. But one bug remained: automatic generated self referencing HTML links included the ':8080' port in their URLs. This is correct because Tomcat only sees requests coming from port 8080 after iptables dnat rule. We have to tell Tomcat that it is behind a kind of proxy and which is the original port number of the requests before being proxied. Fortunatly this is easy to configure in the Catalina connector: just add the 'proxyPort=80' attribute in the server.xml:

<Connector port="8080" maxHttpHeaderSize="8192"
  maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
  enableLookups="false" redirectPort="8443" acceptCount="100"
  connectionTimeout="20000" disableUploadTimeout="true"
  URIEncoding="UTF-8"
proxyPort="80" />

After a restart of Tomcat all generated URLs use the standard port and therefore no explicit port information at all.

Pros of using Tomcat without Apache

  • No need to keep 2 configurations in sync
  • No need to learn 2 different configuration syntax
  • Improved security with only one configuration and server to secure
  • Improved latency because requests and responses don't need to travel through 2 daemons
  • Less memory and CPU needed, improved performance
  • Bigger Java applications run on small hardware
  • Highly dynamic web applications don't benefit from static servers like Apache
  • One component less to update, monitor, configure, load-balance, administrate

Cons of using Tomcat without Apache

  • No PHP or Perl or Python or Ruby support as integrated Apache modules, only CGI
  • Therefore no more Confixx, Plesk, or PhpMyAdmin
  • No more mod_rewrite (*sniff*!)
  • Maybe a front-end Apache is the mandatory architecture at your company or provider
  • Less security because network packets from the Internet reach Tomcat
  • No application level gateway, no Denial-of-Service-Attack-Countermeasure, no Intrusion Detection System

Alternatives to Apache (and Tomcat)

  • lighttpd alias 'lighty' for those who need a web server under memory contraint environments
  • Apache portable runtime: Using this connector in Tomcat via JNI you use the same code like the Apache web server, so where should performance differences come from?
  • Jetty web server like when you run Grails in 'production' mode and not as a war archive on Tomcat
  • Sun Glassfish may replace Apache and Tomcat all together in a unified environment if you have the memory available to run it. Very nice web admin gui and almost no restarts necessary.


  Share

Permalink     Kommentare[5]

Related Articles:

Kommentare:

That seems like a lot of fuss and bother to go through when you can just make Tomcat listen on port 80.

Gesendet von RRR am October 21, 2008 at 09:35 PM CEST #

Super Blog, inhaltlich und stylistisch - fantastisch geradezu. Bin gespannt wie es weiter geht.

Gesendet von 62.225.37.72 am October 22, 2008 at 10:36 AM CEST #

You mention the loss of mod_rewrite. An alternative on the Tomcat side would be to use the Tuckey URLRewrite filter. It's almost as powerful. http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.1/index.html

Gesendet von Josh am October 22, 2008 at 02:21 PM CEST #

Read this http://www-128.ibm.com/developerworks/java/library/l-secjav.html

Surprisingly, my earlier comment was deleted :)

Gesendet von Ramesh am October 22, 2008 at 03:50 PM CEST #

>That seems like a lot of fuss and bother to go through when you can just make Tomcat listen >on port 80.

true, however, sane installations will not start tomcat if the ort is privileged. You can but then you will have to run tomcat as root. Thta's not what you want since tomcat doesn't drop privileges like apache does. E.g. a faled applet could end up in giving root privs away.

So listening on port 80 via server.xml basically is not OK.

Gesendet von Roeland am January 31, 2009 at 02:41 PM CET #

Senden Sie einen Kommentar:
Kommentare sind ausgeschaltet.