Fronting Liferay Tomcat with Apache HTTPd daemon

Introduction

So here's my situation...

I've got a Gentoo Linux server sitting around that I wanted to get Liferay 6.0.6 up and running on. Although this blog will cover the setup I did for my Gentoo box, for the most part you should be able to adapt what I've done for your Linux box. Heck, a lot of this will probably work on a Windows system too, but you're on your own as far as that goes...

Installing Dependencies and the Liferay Tomcat Bundle

My system already has the Java SDK, OpenSSL, and other dependent software installed, so I'm not going to rehash that installation and setup. Suffice it to say that you may find yourself installing some missing components along the way to satisfy dependencies...

Gentoo makes installation pretty easy for all of the components that I needed. Specifically I issued the following command:

$ emerge www-servers/apache dev-libs/apr dev-libs/apr-util www-apache/mod_jk

So that installs the basic software for Apache HTTPd version 2.2.17, but doesn't complete the configuration for us.

Next I downloaded the Liferay 6.0.6/Tomcat bundle in preparation for installation.

Now you might be asking yourselves why I didn't install Tomcat using Gentoo's emerge command and then install Liferay into Gentoo's Tomcat. The reason is that Gentoo's Tomcat actually gets installed to many different directories and doesn't retain the 'all in one directory' setup that's pretty standard w/ Tomcat installs. The tomcat/logs directory ends up over in /var/log, the tomcat/temp directory ends up over in /var/tmp, the tomcat/bin, tomcat/lib, and tomcat/webapps directories end up in /usr/share/tomcat-6, and tomcat/conf ends up in /etc. From a Linux standards perspective, this reorganization makes total sense. Knowing all of the reconfiguration I'd be doing in order to get Liferay up and running in this setup seems to be more trouble than it's worth, at least in the short term. Who knows, maybe if I get some time I'll explore what is involved in doing it the Gentoo way, but for now I've decided to skip it...

Instead I expanded the Liferay 6.0.6 Tomcat bundle to /opt, with the final installation path as /opt/liferay-portal-6.0.6. To make upgrading easier, I created a symbolic link as /opt/liferay using the following command:

$ ln -s /opt/liferay-portal-6.0.6 /opt/liferay

So the path for tomcat is now /opt/liferay/tomcat-6.0.29, and I created another symlink for that as /opt/liferay/tomcat.

The first thing I did was delete the provided JRE that is part of the bundle. This makes the startup.sh and shutdown.sh scripts unhappy as they want to use that JRE, so I had to edit them to use my installed Java environment. I also took the opportunity to hard code the CATALINA_HOME environment variable and tweak the Java command line arguments for memory handling, timezone, etc.

From here you'll want to skip over to Liferay.com and use their documentation to get your database defined, mail server changes done, and fix up your portal-ext.properties files.

At the end of all of this configuration, I could start up Tomcat and hit Liferay by going to Tomcat's port 8080 in order to verify that it was up and running.

So next we have to worry about setting up Apache so that it can front Tomcat. A lot of folks have trouble doing this (you'll see a lot of questions and stuff when you search your favorite search engine). I have to admit that I had to go back and forth tweaking the files until I got it all right...

So now I'm going to be referring to the Apache config files, specifically as initially installed in my Gentoo system. The file paths will probably be different on your system, but the content of the changes should basically be the same...

Configure mod_jk

Gentoo installed mod_jk as part of our previous emerge command, but we need to enable it so Apache will use it when it is running. So we have to edit /etc/conf.d/apache2 and find the line with the APACHE2_OPTS defined. At the end of the line (but still within the quotes), add -D JK. This will enable the loading of the mod_jk when Apache starts up.

The default configuration for mod_jk as installed in Gentoo is pretty complete and shouldn't require any significant editing. The only change I had to make to /etc/apache2/modules.d/88_mod_jk.conf was to change the only uncommented JkMount line so it read:

JkMount /* ajp13

I also changed the JkAutoAlias so that it pointed to /opt/liferay/tomcat/webapps, but honestly I don't know if it was really necessary or not.

Now, the one thing you'll see going forward is that I actually have the JkMount thing in another file. This change was the most obvious one (I mean, the default Gentoo file already had a JkMount here), but it didn't work the first time I started Apache up. So there will be another place in this blog where the JkMount will come up again, and if you do them all you should have the same success that I had.

Gentoo's workers file is /etc/apache2/jk-workers.properties. It's got a lot of comments in it, but basically you should end up w/ the following:

worker.list=ajp13,jkstatus
worker.ajp13.type=ajp13
worker.ajp13.host=localhost
worker.ajp13.port=8009
worker.jkstatus.type=status

The ajp13 is actually going to be our Liferay/Tomcat guy. Perhaps I should have changed it to, say, liferay, but I didn't feel that I wanted to make such sweeping changes to Gentoo's default config.

I said the JkMount would come up again, and here it is. I had to modify the /etc/apache2/vhosts.d/default_vhost.include file, and I added the following:

<IfModule jk_module>
  JkMount /* ajp13
</IfModule>

This change applies the JkMount to the default virtual host, and was necessary for Apache to pass the requests through to Liferay.

After these changes were made, I could fire up Apache and hit the regular port 80 of Apache and it passed the requests through to Tomcat, and it was all working great!

Have Apache Serve Liferay Static Content

The best reason to front Liferay/Tomcat with Apache is to let Apache handle the serving of the static content (images, stylesheets, etc) and let Tomcat deal w/ the dynamic content.

To do this, you're going to have to do some directory copying... First copy the /opt/liferay/tomcat/webapps/ROOT/html directory to Apache's htdocs directory, /var/www/localhost/htdocs in my case. You should also copy all of the other webapps directories (all except for ROOT) to the htdocs directory. By copying all of these directories, any incoming requests for static content will be handled by Apache rather than Tomcat.

NOTE: As you redeploy your portlets, themes, etc. to Liferay, you should also copy the directories over to the htdocs directory, otherwise Apache might serve an older version of the file(s).

For Apache to handle static files, you need to go back to the /etc/apache2/vhosts.d/default_vhost.include file and add some lines just below the JkMount line you added earlier. You'll end up with the following:

<IfModule jk_module>
  JkMount /* ajp13

  JkUnmount /*.jpg ajp13
  JkUnmount /*.jpeg ajp13
  JkUnmount /*.gif ajp13
  JkUnmount /*.png ajp13
  JkUnmount /*.ico ajp13
  JkUnmount /*.css ajp13
  JkUnmount /*.js ajp13
</IfModule>

By using JkUnmount, you're indicating to Apache that it should handle requests with the given extension(s) rather than passing them through to Tomcat.

The one obvious extension that is missing from the above is the .html extension. Since the servlet mapping mechanism in a web application can map .html extensions to a servlet, adding this extension might not give you the result you're expecting. The way I figure it, it's better to let Tomcat serve the single html file (if it is static) rather than break some servlet or portlet functionality, but it is really just a matter of research in the various web.xml files to see if you have any servlet mappings expecting .html extensions. If you don't have any such mappings (now or in the future), you can add the extension as a JkUnmount and let Apache handle them. If you do have the mappings, expect to have the mappings, or just don't want to do the research, then leaving the JkUnmount out for this extension is the safest bet.

Since we're talking about JkUnmounts, if you have other directories in your htdocs folder that Apache should always handle, then add them as JkUnmounts. For example, say I have a javadocs directory in my htdocs folder and I need Apache to handle it, I'd add the following line:

  JkUnmount /javadocs/* ajp13

Setup Liferay To Use Apache

The final step involves editing your /opt/liferay/tomcat/webapps/ROOT/WEB-INF/classes/portal-ext.properties file to include the following:

    web.server.http.port=80
    web.server.https.port=443

This ensures that Liferay will know that it is operating behind Apache HTTPd and will handle redirects correctly.

That's all there is to it. The fact that you're seeing this on port 80 rather than 8080 is proof that these instructions work!

Blogs
[...] I reposted it on Liferay.com as a blog entry here: http://www.liferay.com/web/26526/blog/-/blogs/fronting-liferay-tomcat-with-apache-httpd-daemon Sign in to vote. Flag Please sign in to flag this... [...] Read More
[...] I have re-found that, searching in google the title of the article: http://www.liferay.com/web/26526/blog/-/blogs/fronting-liferay-tomcat-with-apache-httpd-daemon Sign in to vote. Flag Please sign... [...] Read More
I followed the steps and it is working fine, now I need to configure SSL. I have configured the SSL configuration in pache and tomcat both can you tell me what additional steps are reuired.
to get Apache to serve static resources there is also the no-jk command ; here is an example:

SetEnvIfNoCase Request_URI ^/static/.*$ no-jk
Hi David,
Nice post, very helpful.

I need to figure out that since Liferay theme's css is processed request time how do we upload it to Apache web server? Because when I saw files generated in custom theme's /docroot/css/* folder I see .scss files with $variables, I believe these files are processed request time and these variables are resolved by Liferay before sending response.
The .scss files get compiled into the css files, so they will be dynamic in a sense, although the compilation only occurs once (hence folks having issues w/ changed scss files not getting recompiled into css for awhile).

When you have the css files (the ones the .scss get compiled into), those you can treat as static for apache.

Honestly, though, I think you're better off using something like varnish, as it will allow for Liferay to generate the dynamic content yet cache it so it doesn't get created again, and it has the side benefit of not requiring all of the copies of files for apache httpd and tomcat in order to work right.
Excellent Blog David, most helpful. I had went through number pf blogs but this one is most informative, Thanks!
I just used this as a reference for setting up Liferay 7.0 on a Google Compute virtual machine. I had to make a few changes using Ubuntu, but this is still an extremely helpful post. Thank you!