Apache + Tomcat VS Stand Alone Tomcat or GlassFish
I am setting up a Debian server to serve Java web applications. I have done quite a bit of research for several weeks now. Tomcat's web site says it is better to use stand alone Tomcat for speed if you are not clustering. However, I have seen many people suggest that using Apache + Tomcat gives you better security and protection against attacks.
Please assume that the process will be running on port 80 as an unprivileged user. I would assume that if you are running a firewall in front the server, Tomcat should be fine. If, however, you just want to run an exposed web server using Linux firewall, what is the best option?
Or maybe someone can recommend another open source web server. I am trying to keep the solution as light as possible as these webapps will be running in containers.
All opinions welcome and valued.
From my own experience, It's wise to keep something in front of Tomcat to shield it a bit from the outside world. If you run tomcat with the Tomcat-native extension, IO are very fast and Tomcat will behave very well.
Also Tomcat can run on port 80 without running in root by using jsvc which is, if not provided with your distro, very simple to build and use.
However keeping a simple Web frontend just in case is also useful: because this frontend can give you the small touch of flexibility you'll never have with Tomcat (gzip on the fly, rewrite rules, handle more than one tomcat on the same IP:Port using simple virtualhost and proxy mapping,... )
Apache2 can be this frontend using mod_proxy + AJP. AJP handles headers and source IP forwarding to the Tomcat and you'll never be much happier when you'll have to add RewriteRules on your domain because Apache provides that in a very simple way.
However, AJP is very slow to pick the webapp status change and having to wait 30 seconds when your webapp restarts to see it available again on the internet is VERY frustrating. There are also some not so nice issues in latest AJP + Tomcat combination leading to empty pages and broken content type (can be fixed though, but by giving up the tomcat-native enhancements...).
The simple HTTP Mod_proxy can also be used, but by not being a real proxy (Apache changes the Host: header, source IP becomes proxy address,...) is something I don't really like.
Other nice alternatives include:
HAProxy: Very smart and simple proxy, very good at handling load, quite simple to configure, rock solid and a real HTTP Proxy, can forward the source IP via the usual X-Forwarded-For Header. I use this in production and I'm very happy about that. It can scale up to thousands of live connection while restricting the number of active connections to your backend and has many nice features built-in. However, it is probably not fit to make something much more clever than HTTP routing (like RewriteRules for example).
Nginx: I've heard this server do actually support AJP. Being lighter than Apache and more full-featured than HAProxy, I'll probably try this today if I had the opportunity.
Conclusion
- If you have some time for testing, try Nginx,
- If you prefer having a simple and solid frontend, go for HAProxy,
- If you prefer the "traditionnal" route, go for Apache2+AJP,
- If you think Tomcat will be strong enough and will provide you all the features you need, use jsvc and put Tomcat on port 80
The problem that I've run into with both Tomcat and Glassfish on UNIX is that (because they are Java applications I suppose) they cannot bind to port 80 and then drop root privileges. Running these types of things as root isn't a best practice, so that leaves two options:
(1) Run the application server as a regular user bound to a high port (say 8080) and use something like an iptables rule to redirect port 80 traffic to port 8080. I've done this with some Glassfish servers on Linux and it worked very well.
(2) Run the application server as a regular user behind Apache. Apache can bind to port 80, drop privileges and then proxy the requests on to your application server on a high port.
I prefer the latter, but mostly because I have worked with Apache for a long time and find it convenient to configure and manage. So if you know Apache well use it, you'll be happy you did when you need to rewrite some URLs on the fly or tune expiration headers. On the other hand if you have no Apache experience (or in this case since you need things to be as lightweight as possible) it might be easier to stick to just Tomcat and use iptables.
Following on from @deutsch's answer, Tomcat does NOT have to run as root on UNIX. If you install it from a package, e.g. the tomcat6 RPM for Fedora / CentOS / Red Hat, it will run as user tomcat with a restricted set of privileges.
Having said that, I agree with @Deutsch's last paragraph; use Apache as a front end to Tomcat unless you're under a very restrictive deadline to get deployed. Even if you're not that familiar with it yet, it's easy to get a basic deployment going with mod_proxy in front of Tomcat, and you will almost certainly benefit from the increased flixibility and security down the line.