See "SOLVED - Apache/Tomcat/AJP and Subdirectories"

Trying to solve a problem I am having with sub directories in ALL OF MY CF APPS after an upgrade of my server.

I think there is a problem with the AJP1.3 config somewhere but it doesn’t make sense, because all CFM apps and pages work EXCEPT in subdirectories.

Also, I have a test system set up at Digitial Ocean, same OS and everything, same set up. And it’s having the same problem.

HTML files work just fine in subdirectories.


/web/index.cfm  - works
/web/formToDoSomething.cfm - works (and data goes into the database)

/web/admin/abd.cfm - does not work (browser downloads the file)
/web/anyNameYouChoose/abcd.cfm - does not work (browser downloads the file)

/web/anyNameYouChoose/abcd.html - works no problem
/web/anyNameYouChoose/abcd.php - works no problem

I have two legacy apps that worked fine in Railo 3.x. The directories are unchanged, same location, structure, code, etc. All I have done once I upgraded the system and Tomcat, JDK, Lucee, etc, is swap out the previous Railo 3.x WEB-INF with a new Lucee 5.x WEB-INF.

Some more experienced admins might want to know how I handled the updgrade…

Broadly speaking, the upgrade process went like this…

  • Shutdown all services except DNS, SSH
  • Remove all prior Railo instances in web directories
  • Remove Tomcat
  • Uninstall prior JDK (v6)
  • Uninstall MySQL 5.1.x
  • Uninstall PHP
  • Rename prior /etc/apache2 directory for future reference


  • Remove any other added packages
  • Upgrade OS, deleting orphans along the way, checking for updates
  • Reinstall above list of items (as well as Apache 2.4), testing each along the way (and all of this had already been tested on virtual instances at Digital Ocean before doing this upgrade)
  • Install PHP 7.3
  • OpenSSL 1.1.1b
  • Set up JDK 11 (10)
  • Set up Tomcat 9
  • Install MySQL 8.x
  • Install Lucee 5.x

Everything working great!

Also, selinux utils are not installed, and app armor is not installed (yet). So those are not interferring.

  • Tomcat admin is working properly
  • Lucee working great
  • CFM apps and code working properly… EXCEPT any subdirectories

It -appears- that AJP1.3 is not receiving files from sub directories at all. Apache is just saying “OK” (200) and handing it to the browser to do what it wants.

Here is how I have Apache and virtual host configured

Apache modules enabled
(mod_jk can be enabled or not and it makes no difference with this problem, so it is not enabled now).

 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 log_config_module (static)
 logio_module (static)
 version_module (static)
 unixd_module (static)
 access_compat_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 authn_core_module (shared)
 authn_file_module (shared)
 authz_core_module (shared)
 authz_host_module (shared)
 authz_user_module (shared)
 autoindex_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 expires_module (shared)
 filter_module (shared)
 headers_module (shared)
 mime_module (shared)
 mpm_event_module (shared)
 negotiation_module (shared)
 proxy_module (shared)
 proxy_ajp_module (shared)
 proxy_connect_module (shared)
 proxy_fcgi_module (shared)
 proxy_html_module (shared)
 proxy_http_module (shared)
 reqtimeout_module (shared)
 rewrite_module (shared)
 setenvif_module (shared)
 socache_shmcb_module (shared)
 ssl_module (shared)
 unique_id_module (shared)
 xml2enc_module (shared)

Virtual host config relevant portion

	DirectoryIndex index.cfm index.html
	RewriteEngine On
	RewriteOptions Inherit
	Include /etc/apache2/my-apache-cf-ajp.conf

Content of the above listed include file: /etc/apache2/my-apache-cf-ajp.conf

# Start: Tomcat for Lucee configuration with proxy+ajp13:

ProxyPreserveHost On
ProxyPassMatch ^/([cm])(/.)?$ ajp://$1$2
ProxyPassMatch ^/((flashservices/gateway|messagebroker/|flex2gateway/|openamf/gateway/).) ajp://$1

No errors in Tomcat, No errors in Lucee, no Apache errors or SSL errors.


Tomcat logs show the file in the /admin/ subdirectory as existing (which it is):

Log file from /opt/tomcat/logs/ (for this particular site) - - [13/Mar/2019:13:53:58 -0400] "GET /admin/index.cfm HTTP/1.1" 200 1169 - - [13/Mar/2019:13:56:16 -0400] "GET /admin/index.cfm HTTP/1.1" 200 1169 - - [13/Mar/2019:13:56:34 -0400] "GET /admin/index.cfm HTTP/1.1" 200 1169

Apache log also shows the file as existing (and it does)

[13/Mar/2019:13:56:34 -0400] "GET /admin/index.cfm HTTP/1.1" 200 1820

So, Apache says yeah, it’s here, hands off to Tomcat via mod_proxy (?) and Tomcat says yeah, it’s here. But it doesn’t get handed off to Lucee maybe ??? That would be… impossible??? since anything in the root is being passed to Lucee. Yes? No?


Relevant section:

[ssl:debug]  ssl_engine_kernel.c(383): Subsequent (No.3) HTTPS request received for child 68 (server
[authz_core:debug]  mod_authz_core.c(846): authorization result: granted (no directives)
[proxy:debug]  mod_proxy.c(1248): Running scheme ajp handler (attempt 0)
[proxy_ajp:debug]  mod_proxy_ajp.c(744): serving URL ajp://
[proxy:debug]  proxy_util.c(2319): AJP: has acquired connection for (*)
[proxy:debug]  proxy_util.c(2372): connecting ajp:// to
[proxy:debug]  proxy_util.c(2581): connected /admin/index.cfm to
[proxy:debug]  proxy_util.c(3050): AJP: connection established with (*)
[proxy_ajp:debug]  mod_proxy_ajp.c(269): APR_BUCKET_IS_EOS
[proxy_ajp:debug]  mod_proxy_ajp.c(275): data to read (max 8186 at 4)
[proxy_ajp:debug]  mod_proxy_ajp.c(289): got 0 bytes of data
[proxy_ajp:debug]  mod_proxy_ajp.c(639): got response from (null) (*)
[proxy:debug]  proxy_util.c(2334): AJP: has released connection for (*)

I would make the following changes:

ProxyPreserveHost On
ProxyPassMatch ^/([cm])(/.*)?$ ajp://$1$2

Just so I am clear, that is ALL you would have in the include file?

Mine has a few more lines for security on average but you did not need to run two lines of code for ProxyPassMatch

Unless you have a specific need, you do not need images or other mime types passed to Lucee.

I would ditch timeouts, as in a proxy configuration, You are just timing out your proxy connections, which does not make sense.

I would use something like this, and is closer to most working configs I handle.

ProxyPreserveHost On
ProxyPassMatch ^/([cm])(/.)?$ ajp://$1$2
ProxyPassMatch ^/((flashservices/gateway|messagebroker/|flex2gateway/|openamf/gateway/).
) ajp://$1

I tried that, still nothing. /admin/index.cfm just downloads (depending on browser).

Also updated my original post to reflect this.

I am not thrilled the way ubuntu handles security

If you have not already, try disabling selinux, even temporarily, and restarting your web services

setenforce 0

Selinux-utils were not installed at all.

No go. Still downloads the index.cfm file.

If someone is willing to help out, I can provide access or share screen. I have a feeling it’s something stupid in Apache.

it’s possible that Tomcat is delivering the CFM as a binary. Do things work okay if you browse the site using Tomcat’s http port?

also, the subject of this thread says “solved”, but the last post doesn’t make it sound like it is.

Please see new thread - SOLVED - Apache/Tomcat/AJP and Subdirectories

I put it in a new thread to make the answer clear. Why the appBase was the problem, I don’t fully understand. In every prior instance of running OpenSource CF engines (BlueDragon, Railo), the appBase has been the same as the docBase.

The corect setting for my virtual host(s) in the /opt/tomcat/conf/server.xml file is;

<Host name="" appBase="webapps" unpackWARs="true" autoDeploy="true">
	<Context path="" docBase="/path/to/websites/project/" />
	<Valve className="org.apache.catalina.valves.AccessLogValve" 
		directory="logs" prefix="" suffix=".log" 
		pattern="%h %l %u %t &quot;%r&quot; %s %b" />

So, made the appBase=“webapps” instead of the path to the web root of the virtual host.

And just like that, everything is working.

And to test, I also made the same change on the test bed currently running at Digital Ocean. Same result - success!! Even though there are differences in the ProxyPassMatch directives between the two setups just for the sake of testing.

My production settings for ProxyPassMatch are more extensive than the one at Digital Ocean, but it doesn’t have any affect in this case. You can get by with the minimum as Terry pointed out:

ProxyPreserveHost On
ProxyPassMatch ^/([cm])(/.)?$ ajp://$1$2
ProxyPassMatch ^/((flashservices/gateway|messagebroker/|flex2gateway/|openamf/gateway/).) ajp://$1

Looking at the difference in the Tomcat logs at startup, I recall now how the proper install should look. Over the last few days I’ve been seeing Tomcat deploy to lots of subdirectories which was strange. If you see that in your log, you’ve configured the server.xml incorrectly.

So, I’d love to know why appBase=“webapps” is now correct. And yet, I still copy over (cp -P /opt/tomcat/webapps/root/Web-INF) to the root of my website because that seems to work better than just creating an empty WEB-INF.

Commentary? Feel free…