November 2024
M T W T F S S
 123
45678910
11121314151617
18192021222324
252627282930  

Categories

November 2024
M T W T F S S
 123
45678910
11121314151617
18192021222324
252627282930  

mod_jk or mod_proxy_ajp ?

mod_jk or mod_proxy_ajp ?

A Tomcat servlet container can be put behind an Apache web server using the AJP protocol, which carries all request information from Apache to Tomcat. There are two implementations of AJP module:

  • mod_jk which must be installed separately
  • mod_proxy_ajp which is a standard module since Apache 2.2

They both use protocol AJP, so they both provide the same functionality.

The advantage of mod_jk is its JkEnv directive, that allows to send any environmental variable from Apache to Tomcat as a request attribute. If you need to get for example the SSL_CLIENT_S_DN variable with SSL certificate DN provided by mod_ssl, or the AUTHENTICATE_CN variable provided by mod_ldap, then mod_jk can be directed to send it using simply:

<IfModule mod_jk.c>
   JkEnvVar SSL_CLIENT_S_DN
</IfModule>

while for mod_proxy_ajp, you have to use mod_rewrite to prepend AJP_ prefix to variables that you want to send:

<IfModule mod_proxy_ajp.c>
   RewriteRule .* - [E=AJP_SSL_CLIENT_S_DN:%{SSL:SSL_CLIENT_S_DN}]
</IfModule>

which is more complicated and forces you to activate the mod_rewrite.

The advantage of mod_proxy_ajp is that it is a standard Apache module, so you do not need to compile and install it itself.

An example configuration of mod_jk in Apache http.conf file is as follows:

<IfModule mod_jk.c>
 # a list of Tomcat instances
 JkWorkerProperty worker.list=tomcatA,tomcatB
 # connection properties to instance A on localhost
 JkWorkerProperty worker.tomcatA.type=ajp13
 JkWorkerProperty worker.tomcatA.host=localhost
 JkWorkerProperty worker.tomcatA.port=8009
 # connection properties to instance B on some other machine
 JkWorkerProperty worker.tomcatB.type=ajp13
 JkWorkerProperty worker.tomcatB.host=zeus.example.com
 JkWorkerProperty worker.tomcatB.port=8009
 # some other configuration
 JkLogFile "|/usr/bin/cronolog /var/log/apache2/%Y/%m/%d/mod_jk.log"
 JkLogLevel error
 JkShmFile /var/log/apache2/jk.shm
 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
 # forwarding URL prefixes to Tomcat instances
 JkMount /opencms tomcatA
 JkMount /otherapp tomcatB
</IfModule>

An example configuration of mod_proxy_ajp is here:

<IfModule mod_proxy_ajp.c>
 <Location "/opencms">
   Allow from all
   ProxyPass ajp://localhost:8009/opencms
 </Location>
 <Location "/otherapp">
   Allow from all
   ProxyPass ajp://zeus.example.com:8009/otherapp
 </Location>
</IfModule>

So mod_jk has more flexible configuration, but needs a separate installation and its configuration is more complex. If you have no special requirements, go for mod_proxy_ajp. If you need something special, like to use authentication modules from Apache for securing applications in Tomcat, go for mod_jk.

New site configuration

If you are running OpenCms (6.0 or greater) in Tomcat using an Apache front end (with mod_jk or mod_proxy_ajp, NOT MOD_PROXY IN HTTP MODE), there are three basic steps to configuring a new site in your implementation:

Create the containing folder for the site in the OpenCms Explorer

In the OpenCms Explorer view, change to the ‘/’ site, go into the ‘sites’ folder, and create a new folder. The folder name is case-sensitive, so keep track of exactly what you entered. For the examples that follow, we’ll assume the creation of a /sites/MyNewSite folder.

Add site information to OpenCms’s configuration

In order to make your new site available within OpenCms (i.e. displayed in the site list of the workplace), we need to modify the opencms-system.xml configuration file, located in <opencmsroot>/WEB-INF/config/.

Find the section of opencms-system.xml that looks like:

 <sites>
    <workplace-server>http://www.mysite.com</workplace-server>
    <default-uri>/sites/default/</default-uri>
    <site server="www.mysite.com" uri="/sites/default/"/>
 </sites>

and add another site definition as follows:

    <site server="www.mynewsite.com" uri="/sites/MyNewSite/"/>

This tells OpenCms that when it receives a request for www.mynewsite.com, it should serve that request out of the MyNewSite container. I believe you have to restart tomcat or reload opencms for this config file to be reread.

Adjust OpenCms automatic link generation (static export, module-resources)

This configuration is only valid if OpenCms is installed as the ROOT application in Tomcat. Edit the file “WEB-INF/config/opencms-importexport.xml” in your OpenCms installation and change the content of the <vfs-prefix> tag to empty:

<rendersettings>
  <rfs-prefix>${CONTEXT_NAME}/export</rfs-prefix>
  <vfs-prefix></vfs-prefix>
</rendersettings>

Then all links will have empty prefix, i.e. a link to the file /dir/file.html will be /dir/file.html instead of /opencms/dir/file.html.

Configuring the Apache WebServer

http.conf

Add the following lines to the http.conf file if needed (not already be done) to load the modules needed. Other apache distributions recommend to configure the modules to load on different locations. For apache 2.2 on SuSE-release this is e.g. done in /etc/sysconfig/apache2. On Debian, use the a2enmod command to link the files from /etc/apache2/mods-available to /etc/apache/mods-enabled. In the end, the following lines need to be somehwo included in the Apache configuration:

LoadModule jk_module modules/mod_jk.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule rewrite_module modules/mod_rewrite.so

After the modules are loaded they have to be configured.

mod_jk

If you use mod_jk, put there the following:

<IfModule mod_jk.c>
 JkWorkerProperty worker.list=ocms
 JkWorkerProperty worker.ocms.type=ajp13
 JkWorkerProperty worker.ocms.host=localhost
 JkWorkerProperty worker.ocms.port=8009
 JkLogFile "|/usr/bin/cronolog /var/log/apache2/%Y/%m/%d/mod_jk.log"
 JkLogLevel error
 JkShmFile /var/log/apache2/jk.shm
 JkOptions +RejectUnsafeURI
 JkMount /opencms/* ocms
 JkMount /export/* ocms
 JkMount /resources/* ocms
 JkMountCopy All
</IfModule>

The JkMount directives forward requests to the OpenCMS servlet at /opencms and the directories at /export and /resources to Tomcat. The JkMountCopy All directive mount that for all virtual servers. If you plan to use some virtual servers without OpenCMS, do not put the directives here, but mount the prefixes in each virtual server.

mod_proxy_ajp

If you use mod_proxy_ajp, put there the following:

  <IfModule mod_proxy_ajp.c>
   <Location "/opencms">
    Allow from all
    ProxyPass ajp://localhost:8009/opencms
   </Location>
   <Location "/export">
    Allow from all
    ProxyPass ajp://localhost:8009/export
   </Location>
   <Location "/resources">
    Allow from all
    ProxyPass ajp://localhost:8009/resources
   </Location>
   <Location "/update">
    Allow from all
    ProxyPass ajp://localhost:8009/resources
   </Location>
  </IfModule>

Defining the virtual hosts

This configuration is for an OpenCms installation which is installed as the ROOT application in Tomcat.

<VirtualHost *:80>
  ServerName www.mysite.com
  ServerAdmin admin@example.com
  DocumentRoot "C:/Tomcat5.5/webapps/ROOT"
  ErrorLog logs/error.log

  # Allow accessing the document root directory 
  <Directory "C:/Tomcat5.5/webapps/ROOT">
    Options FollowSymlinks
    AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>
  
  # If the requested URI is located in the resources folder, do not forward the request
  SetEnvIfNoCase Request_URI ^/resources/.*$ no-jk
  
  # If the requested URI is static content do not forward the request
  SetEnvIfNoCase Request_URI ^/export/.*$ no-jk
  RewriteEngine On
  RewriteLog logs/rewrite.log
  RewriteLogLevel 1

  # Deny access to php files
  RewriteCond %{REQUEST_FILENAME} (.+)\.php(.*)
  RewriteRule (.*) / [F]

  # If the requested URI is NOT located in the resources folder.
  # Prepend an /opencms to everything that does not already starts with it
  # and force the result to be handled by the next URI-handler ([PT]) (JkMount in this case)
  RewriteCond %{REQUEST_URI} !^/resources/.*$
  RewriteCond %{REQUEST_URI} !^/export/.*$
  RewriteCond %{REQUEST_URI} !^/webdav.*$
  RewriteRule !^/opencms/(.*)$ /opencms%{REQUEST_URI} [PT]

  # These are the settings for static export. If the requested resource is not already
  # statically exported create a new request to the opencms404 handler. This has to be
  # a new request, because the current would net get through mod_jk because of the "no-jk" var.
  RewriteCond %{REQUEST_URI} ^/export/.*$
  RewriteCond "%{DOCUMENT_ROOT}%{REQUEST_FILENAME}" !-f
  RewriteCond "%{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index_export.html" !-f
  RewriteRule .* /opencms/handle404?exporturi=%{REQUEST_URI}&%{QUERY_STRING} [P]
  
  JkMount /* ocms
</VirtualHost>

This redirect doesn’t work with opencms 7.5.1 for static export.

RewriteRule .* /opencms/handle404?exporturi=%{REQUEST_URI}&%{QUERY_STRING} [P]

so I change it to:

RewriteRule .* http://127.0.0.1:8080/opencms/handle404?exporturi=%{REQUEST_URI}&%{QUERY_STRING} [P]

After the configuration is finished the Apache WebServer needs to be restarted.

Alternative definition

The previous definition is too complex, here is my simpler definition that works for me:

<VirtualHost 147.251.9.183:80 >
   ServerAdmin admin@example.com
   ServerName www.mysite.com
   DocumentRoot /var/www/mysite
   <Directory /var/www/mysite>
       Options Indexes MultiViews
       AllowOverride None
       Order allow,deny
       allow from all
   </Directory>
   RewriteEngine On
   RewriteRule ^/$ /opencms/ [passthrough]
   RewriteCond %{REQUEST_URI} !^/opencms/.*$
   RewriteCond %{REQUEST_URI} !^/export/.*$
   RewriteCond %{REQUEST_URI} !^/resources/.*$
   RewriteCond %{REQUEST_URI} !^/error/.*$
   RewriteCond %{REQUEST_URI} !^/icons/.*$
   RewriteCond %{REQUEST_URI} !^/update/.*$
   RewriteRule .* /opencms%{REQUEST_URI} [QSA,passthrough]
</VirtualHost>

The configuration rewrites all requests by adding /opencms in front of them, except requests that already have the prefix, or go for static files or go for Apache error files or Apache file icons.

Configuring Tomcat

Make sure the connector to be used by Apache mod_jk is configured in the server.xml file.

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009"
enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>