How to run Tomcat on Port 80

Most people run Tomcat behind another Webserver (like Apache), hence Tomcats connector documentation and the default configuration of Tomcat deal with that situation.

This page is about using Tomcat as a stand alone Webserver.

Does is make sense to run Tomcat on 80 anyway?

Port 80 is the canonical Port for HTTP Servers. Tomcat is a HTTP Server, so the answer is yes.

The main reason for keeping Tomcat only behind another HTTP Server (as Apache) is efficiency. Tomcat is good at serving Servlets (and JSP Pages), but it's not as feature rich when it comes to deal with static content like images or normal html pages or when using other server side languages like php.

But in many cases the overhead of installing, running and maintaining an extra server (and keeping Tomcat talking to that server) can be avoided by using a standalone Tomcat. (Besides, Tomcat-Servers are less likely to be attacked - like a poppy amongst wheat :-)

Windows

If you are running windows you are quite fine. All you have to do is changing the port number in server.xml from 8080 to 80 and you are done. For security concerns ask Bill :-)

Unix

Under UNIX all ports <1024 are "privileged" ports. Only root may open a priviledged port.

authbind is a tool you can use to grant the right to bind() to port 80 to the tomcat user.

Tomcat 5.x or later

Tomcat 5.x can bind to privileged ports using the jsvc interface. The instructions on how to setup Tomcat can be found in the online documentation.

Starting Tomcat 5.x

Instead of using catalina.sh you have to write your own startup script, which issues a command like this one.

jsvc \
      -user $TOMCAT_USER \
      -cp ./bin/bootstrap.jar \
      -outfile ./logs/catalina.out \
      -errfile ./logs/catalina.err \
      -pidfile "$CATALINA_PID" \
      \
      -Djava.endorsed.dirs=./common/endorsed \
      -Dcatalina.home="$CATALINA_HOME" \
      -Djava.io.tmpdir="$CATALINA_TMPDIR" \
      org.apache.catalina.startup.Bootstrap start

The command will create two processes:

  1. One root process opening the port and
  2. one progress running as $TOMCAT_USER actually serving requests.

Note that we create a pid file here. A recommended spot for that file would be /var/run/catalina.pid. We will need that file for shutdown.

Stopping Tomcat 5.x

By starting Tomcat via jsvc, Tomcat enters "daemon mode", which means that it won't listen to port 8005 any more and hence you cannot stop Tomcat via catalina.sh (or shutdown.sh).

All you have to do is sending a SIGTERM or SIGINT to the process belonging to root. In the above case you can find the pid in $CATALINA_PID.

Tools like Daemontools can do the PID handling for you. You just have to replace the option "-pidfile ..."-Option against "-nodetach" to the jsvc options (Thanks to Robin Bowes).

Tomcat 4.1.x

The Jakarta Project Commons-Daemon which is bundled with Tomcat 5.x can also be used with Tomcat 4.1.x (I haven't tried it). From here on I assume that you cannot use jsvc for one or another resaon...

Tomcat as root:

The easiest way would be running Tomcat as root. This is strongly discouraged! Do you really want to run your JSP files as uid root?

However, you can enable security policies (disabled by default). This will lead to a lot of work as the default rules are very restrictive - and error messages from illegal accesses are not very informative.

In contrast to Apache, which changes the uid from root to someone with less rights before serving pages, Tomcat doesn't do that, as the Java VM does not support setuid() calls and Tomcat might be just multithreaded but in a single process (as some VM's don't allow more than one thread).

So you normally want to keep Tomcat serving port 8080 internally.

(you might want to change it to a secret port, but this is another topic :-)

User space port forwarding:

The next simplest way would be using a port forwarder (like "portfwd" or "redir4a") mapping access to port 80 to 8080. These processes may run under root, as they don't do much besides forwarding all packets. Tomcat just serves at 8080 as usual.

This approach has one disadvantage: As these tools exhibit the behaviour of a proxy, for Tomcat all calls look like coming from the local machine - this will render access logs mostly useless.

Kernel space port forwarding:

A better way is to use kernel based port forwarding. This feature is not available for all flavours of Unix, but at least for recent Linux kernels (2.4) it works fine.

Here is a very basic example for iptables in a static environment (static means that the example does not deal with ppp connections properly, you might have to add something similar to your ip-up/down scripts).

iptables -t nat -A OUTPUT -d localhost -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A OUTPUT -d your hostname -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -d your hostname -p tcp --dport 80 -j REDIRECT --to-ports 8080

ipchains (for Linux 2.2. kernels) should work similar - it might also be possible to map the port directly inside your firewall.

Caveat:

Under some circumstances, the HttpConenctor class reports the original port back to the client. Further requests will continue with that port (which is not the desired effect and might even be blocked by your firewall).

Besides switching to a more contemporary Connector like CoyoteConenctor (recommended), you can circumvent that problem by adding a proxyPort to the HttpConnector declaration:

<Connector
  className="org.apache.catalina.connector.http.HttpConnector"
  port="8080"
  proxyPort="80"
>

Other approaches:


<- back Home
Holger Klawitter
Last modified: Thu Jun 27 12:16:59 CEST 2013