Using Tomcat And Apache HTTP Server
Other HTTPD servers (e.g., NGINX) have not yet been explored.
Using Apache as a front-end proxy server for the TDS running on Tomcat is perhaps the easiest method for setting up a reverse proxy for the TDS. There are two methods to accomplish this:
- Apache’s
mod_proxy
in combination with Tomcat’s HTTP connector; or - the
mod_jk
Apache module with the Tomcat AJP connector.
Tomcat-Apache Proxy Documentation
- Tomcat Connectors Documentation describing the difference between the Tomcat HTTP and AJP connectors.
mod_proxy
- Tomcat HTTP Connector Configuration for the Tomcat HTTP connector (for use with Apache’s mod_proxy).
- Tomcat Proxy Support - How To Tomcat documentation showing how to use the build-in Apache module mod_proxy for Apache versions 1.3X and 2.X.
mod_jk
- Tomcat AJP Connector Configuration for the Tomcat AJP connector (for use with Apache’s mod_jk).
-
Tomcat Reverse Proxy - How To Configurations and fine-tuning of a reverse proxy set up using the mod_jk Apache module.
Note: The use of themod_jk
has been tested and vetted by Unidata.
Other modules used for creating a reverse proxy have not yet been explored.
Implementing The Tomcat-Apache Proxy Using AJP
The following example shows how to implement a proxy using the Apache HTTPD server, Tomcat Servlet Container, and Tomcat’s mod_jk
on a linux system.
Install mod_jk
-
Download the latest version of Tomcat’s
mod_jk
module. -
Build and install the
mod_jk
module as per the installation instructions that come bundled with the download. The build and installation will need to be done as eitherroot
,sudo
, or as user with privileges to modify Apache.# tar xvfz tomcat-connectors-1.2.xx-src.tar.gz # cd tomcat-connectors-1.2.xx-src/native # ./configure --with-apxs=/usr/bin/apxs <--- path to your apache apxs # make # make install
Confirm the module was added to the directory in which the Apache HTTPD server stores its modules (
/usr/local/apache/modules
in this example):# cd /usr/local/apache/modules # ls -l mod_jk.so -rwxr-xr-x 1 root root 1147204 Oct 8 12:34 mod_jk.so
Configure Apache HTTP Server To Use mod_jk
To Talk To Tomcat
-
Update Apache configurations to use the
mod_jk
module.mod_jk
was built as a DSO module, therefore you will need to update your Apache configurations to enable this 3rd-party module:The following example shows adding
mod_jk
configurations to a Apache HTTPD 2.4 server built from source.
Modify the main Apache server configuration file (usuallyhttpd.conf
) in the following manner (in this example/usr/local/apache/conf
is where the Apache configuration files are located):# cd /usr/local/apache/conf # vi http.conf
Add the following configurations to enable the
mod_jk
module, restrict access to web applicationWEB-INF
andMETA-INF
directories, and tell Apache where to find theworkers.properties
file using theJkWorkersFile
directive. (Theworker.properties
file is discussed in more detail below.)# Third party modules LoadModule jk_module modules/mod_jk.so <IfModule jk_module> JkWorkersFile "conf/workers.properties" JkShmFile "logs/mod_jk.shm" JkLogFile "logs/mod_jk.log" JkLogLevel warn #Tomcat Security Section <LocationMatch "/WEB-INF/"> Require all denied </LocationMatch> <LocationMatch "/META-INF/"> Require all denied </LocationMatch> </IfModule>
Note: Consult the Tomcat documentation for more information about themod_jk
directives. -
Create a
workers.properties
file.The
mod_jk
modules in the Apache HTTPD server uses theworkers.properties
file to relevant map requests to the TDS using Tomcat’s AJP connector.Use your favorite text editor to create a
workers.properties
file in the Apache configuration directory that you specified in the previous step using theJkWorkersFile
directive:# cd /usr/local/apache/conf # vi http.conf
Add the following configurations to the
workers.properties
module to define aworker
that will handle communication between the Apache HTTPD server and Tomcat.# workers.properties # To allow tomcat and apache to talk to each other. # needed by mod_jk # Define workers worker.list=worker1 # Define workers using ajp13 protocol to forward requests to the Tomcat processes. worker.worker1.type=ajp13 # TDS app # worker1 will talk to Tomcat listening on localhost at port 8009 worker.worker1.host=localhost worker.worker1.port=8009
Note: Consult the Tomcat documentation for more information about the workers.properties file syntax and options. -
Configure your Apache host to send the appropriate requests to TDS via
mod_jk
and Tomcat AJP.You will use the
JkMount
directives that come with themod_jk
to specify/match which URL requests should be proxied to the TDS in the Tomcat Servlet Container.The following shows an example of configuring an Apache
VirtualHost
with theJkMount
directives.
Note that these directives reference theworker
configured in theworkers.properties
file in the previous step.<VirtualHost IP_ADDRESS:PORT> ServerName thredds.unidata.ucar.edu ... # Proxy requests to the TDS JkMount /thredds* worker1 JkMount /thredds worker1 # Proxy requests to the Manager App JkMount /manager* worker1 JkMount /manager worker1 ... </VirtualHost>
Note: Consult the Tomcat documentation for more information about theJKMount
directive.
Configure Tomcat and the TDS for the proxy
-
Modify the Tomcat
AJP Connector
In the
${tomcat_home}/conf/server.xml
file, locate theAJP Connector
(uncommented and enabled by default) and add the following additional configuration to it:<!-- AJP 1.3 Connector on port 8009 --> <Connector port="8009" enableLookups="false" useBodyEncodingForURI="true" connectionTimeout="20000" protocol="AJP/1.3" />
More Information: Consult the Tomcat documentation for more information about the AJP Connector configuration options. -
Disable any active
Java HTTP/1.1 Connector
and theSSL HTTP/1.1 Connector
Tomcat connectors.Important: Only perform this step is you have enabled Apache to handle the SSL/TLS encryption for Tomcat and the TDS.This will prevent direct communication to Tomcat via ports
8080
and8443
ensuring the AJP proxy via Apache is the only HTTP method by which to access Tomcat and the TDS.Locate the
Java HTTP/1.1 Connector
listening on port8080
and the activeSSL HTTP/1.1 Connector
listening on port8443
and comment them out:<!-- <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> --> ... <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig> </Connector> -->
-
Configure the TDS to relinquish control of TLS/SSL to Apache
Important: Only perform this step is you have enabled Apache to handle the SSL/TLS encryption for Tomcat and the TDS.The TDS deployment descriptor (
${tomcat_home}/webapps/thredds/WEB-INF/web.xml
) is configured to only allow access parts of the TDS application via TLS/SSL.
Because we’ve disabled Tomcat’s handling of the TLS/SSL, we need to update these configurations.Use your favorite editor to open the TDS
${tomcat_home}/webapps/thredds/WEB-INF/web.xml
file.
Around line106
you’ll start seeing configurations that look like the following:<!-- tdsConfig with HTTPS needed for /admin access --> <security-constraint> <web-resource-collection> <web-resource-name>sensitive read access</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>tdsConfig</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> ...
These configs restrict access to the url in the
<url-pattern>
tags to the role in the<role-name>
tags (which correspond to the roles defined in the${tomcat_home}/conf/tomcat-users.xml
file).
The<transport-guarantee>CONFIDENTIAL</transport-guarantee>
says access must take place via HTTPS.For any restricted part of the TDS you want to access that is listed here, you’ll need to comment out the configurations in the
<user-data-constraint>
tags:<!-- tdsConfig with HTTPS needed for /admin access --> <security-constraint> <web-resource-collection> <web-resource-name>sensitive read access</web-resource-name> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>tdsConfig</role-name> </auth-constraint> <!-- do not use tomcat https <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> --> </security-constraint> ...
Warning: If you leave outside access to the TDS and Tomcat open via port8080
this once protected portion of the TDS is now open in the clear. Hence, we recommend disabling these connectors if you are using Apache as a proxy.
Also, keep these changes to the configurations in mind if you ever decide to reverse or undo the Apache reverse proxy!
Changing The TDS Context Path (/thredds
)
We do not recommend changing the TDS context path (the /thredds
part of the URL path).
However, if your network configuration requires that you use a different context path (e.g., /my/thredds
) or you are proxying two TDS installations and need to differentiate them with different context paths (e.g., /thredds1
and /thredds2
), you will need to make the following changes:
-
Rename the
thredds.war
file to match the desired context path before you deploy it to Tomcat. Tomcat and other servlet engines direct incoming requests to a particular web application when the beginning of the request URL path matches the context path of that particular webapp. The easiest way to let Tomcat (or any other servlet engine) know what context path to use for a given webapp is to rename that webapp’s.war
file before deploying it to Tomcat.For instance, if you want all URLs starting with
/thredds2
to be handled by your TDS install, rename thethredds.war
file tothredds2.war
before you deploy it to Tomcat.If the desired context path is a multi-level context path (e.g.,
/my/thredds
), you must use a pound sign (“#”) in the.war
filename to encode the slash (/
). In this case, thethredds.war
file would need to be renamed tomy#thredds.war
.Important: The deployment descriptor (web.xml
file) is overwritten during deployment which means this edit must be done every time the TDS is re-deployed. -
Edit the TDS
web.xml
file and change the value of theContextPath
parameter to match the desired context path.The TDS uses the value of the
ContextPath
context parameter (as defined in the TDSweb.xml
file) when generating TDS URLs in certain situations. To make sure all generated URLs are consistent, you must change the value of theContextPath
parameter to match the desired context path.(Changing the value of
ContextPath
will no longer be necessary in a future release once we require Tomcat 6.0 (Servlet 2.5).The TDS
web.xml
file is located in${tomcat_home}/webapps/<contextPath>/WEB-INF/web.xml
, where<contextPath>
is the value of the desired context path. TheContextPath
context parameter is defined in theweb.xml
file (starting at line12
):<context-param> <param-name>ContextPath</param-name> <param-value>thredds</param-value> </context-param>
For the
/thredds2
example, it should be changed to:<context-param> <param-name>ContextPath</param-name> <param-value>thredds2</param-value> </context-param>
And for the
/my/thredds
example, it should be changed to:<context-param> <param-name>ContextPath</param-name> <param-value>my/thredds</param-value> </context-param>
-
Edit your TDS configuration catalogs and change the service base URLs to start with the desired context path.
So that users will receive the correct data access URLs for datasets served by your TDS, the base URLs given by the
service
elements in your TDS configuration catalogs must match the desired context path.An OPeNDAP service element on a TDS with the context path of
/thredds2
would need to look similar to this:<service name="odap" serviceType="OPeNDAP" base="/thredds2/dodsC/"/>
And, similarly, an OPeNDAP
service
element on a TDS with the context path of/my/thredds
would need to look similar to this:<service name="odap" serviceType="OPeNDAP" base="/my/thredds/dodsC/"/>
Troubleshooting Tips
- Check the catalog URL in the title of the HTML view of catalogs matches the requested URL.
- Check the Data Access URL in the OPeNDAP Data Access Form matches the requested URL (minus the
.html
suffix). - If you have TDS Remote Management configured, go to the TDS debug page (e.g., http://localhost:8080/thredds/admin/debug) and follow the “Show HTTP Request info” link.
-
Once there, check the values listed for server name and port and the context path all match the appropriate values from the request URL, e.g., for the URL http://localhost:8080/thredds/admin/debug?General/showRequest , the values should be:
req.getServerName(): localhost req.getServerPort(): 8080 req.getContextPath(): /thredds