0

I'm installing a JSP webapp on Ubuntu 24.04 using Tomcat 10 and Java 11. The app is designed to have Apache proxy JSP requests to Tomcat via AJP. It has worked with previous versions of Ubuntu, Tomcat and Java going back to at least 2014.

When I attempt to access the index page of the app on the new system, the server returns a "503 Service Unavailable" error. As far as I can tell, I'm setting it up exactly like previous instances that have worked.

  • Apache's mod_proxy and mod_ajp are both enabled:
$ ls /etc/apache2/mods-enabled | grep "prox" lrwxrwxrwx 1 root root 32 Mar 17 13:02 proxy_ajp.load -> ../mods-available/proxy_ajp.load lrwxrwxrwx 1 root root 28 Mar 17 13:02 proxy.conf -> ../mods-available/proxy.conf lrwxrwxrwx 1 root root 28 Mar 17 13:02 proxy.load -> ../mods-available/proxy.load 
  • Tomcat's /etc/tomcat10/server.xml has its AJP Connector enabled:
 <Connector protocol="AJP/1.3" address="::1" port="8009" proxyPort="443" redirectPort="8443" maxParameterCount="1000" enableLookups="false" URIEncoding="UTF-8" secretRequired="false" /> 

Note that I've included the secretRequired="false" gotcha from Tomcat 9 that was the problem last time.

  • Apache is configured to proxy to Tomcat:
<VirtualHost 139.93.241.16:80> # Server Name ServerName webapp.com # Tomcat proxy Information ProxyRequests Off ProxyPassReverse / ajp://localhost:8009/ ProxyPassMatch ^/(.*)\.jsp$ ajp://localhost:8009/$1.jsp ProxyPassMatch ^/$ ajp://localhost:8009/ </VirtualHost> 
  • Apache and Tomcat are both running.

If I comment out the Proxy directives in the Apache configuration, the URL http://webapp.com shows the Ubuntu Apache default page, as expected. If I directly access Tomcat using http://webapp.com:8080, I get the default ROOT/index.html page of the Tomcat webapp. This shows that both Apache and Tomcat are working individually. It's only when I enable proxying in the Apache config that I get the 503 error instead of the default webapp home page for http://webapp.com.

When I attempt to load http://webapp.com, the Apache error log at /var/log/apache2/error.log gives this error:

[Fri May 09 14:04:36.608181 2025] [proxy:error] [pid 273783] (111)Connection refused: AH00957: AJP: attempt to connect to 127.0.0.1:8009 (localhost:8009) failed [Fri May 09 14:04:36.608221 2025] [proxy_ajp:error] [pid 273783] [client 110.71.264.19:37120] AH00896: failed to make connection to backend: localhost 

I've searched for these errors, but they are so generic that I haven't been able to find anything relevant to this case.

The Tomcat error log at /var/log/tomcat10/catalina.out shows no records related to these attempts to access the resource, which is consistent with it not receiving the proxy request from Apache (I've configured systemd on Ubuntu to send Tomcat logs to catalina.out instead of journalctl).

I've accounted for everything on the Tomcat 10 migration guide that I can tell is relevant, as well as the Proxy How-to and Reverse Proxy How-to.

What am I missing? What's the next thing I should check to troubleshoot this issue?

3
  • 1
    The reverse proxy is connecting on IPv4 & Tomcat is listening on IPv6. Commented May 10 at 20:36
  • shortly said, try ::1 instead ;) Commented May 11 at 8:23
  • @djdomi I would say this is simpler to fix on Tomcat, but both will do the trick. Commented May 11 at 10:19

1 Answer 1

3

The Apache error log says it is failing to connect to 127.0.0.1:8009 in plain English:

AH00957: AJP: attempt to connect to 127.0.0.1:8009 (localhost:8009) failed

The reverse proxy is connecting on IPv4 (to 127.0.0.1) & the Tomcat is listening on IPv6 (::1).

Fix on Tomcat side

The documentation for the Tomcat 10.0 AJP Connector describes the attribute address:

For servers with more than one IP address, this attribute specifies which address will be used for listening on the specified port. By default, the connector will listen on the loopback address. Unless the JVM is configured otherwise using system properties, the Java based connectors (NIO, NIO2) will listen on both IPv4 and IPv6 addresses when configured with either 0.0.0.0 or ::. The APR/native connector will only listen on IPv4 addresses if configured with 0.0.0.0 and will listen on IPv6 addresses (and optionally IPv4 addresses depending on the setting of ipv6v6only) if configured with ::.

You have set address="::1", limiting the connector only to listen on the IPv6 loopback address. Removing this will revert it back to the default configuration; listening on both IPv4 (127.0.0.1) and IPv6 (::1) loopback addresses.

Fix on Apache reverse proxy side

Using ajp://localhost:8009/ with DNS name localhost does not have control over which IP address the reverse proxy will use. As the log says, it is using IPv4 127.0.0.1. You could explicitly define either IPv4 or IPv6 address (::1) there.

It might be a bit hidden in the Apache 2.4 documentation, but both Binding to Addresses and Ports & <VirtualHost> Directive gives indirect hints that IPv6 addresses must be enclosed in square brackets.

IPv6 addresses must be specified in square brackets because the optional port number could not be determined otherwise.

An example on how to apply this to your AJP reverse proxy configuration using mod_proxy_ajp:

ProxyPassMatch ^/(.*)\.jsp$ ajp://[::1]:8009/$1.jsp ProxyPassMatch ^/$ ajp://[::1]:8009/ ProxyPassReverse / ajp://[::1]:8009/ 
2
  • Thank you. address="::1" in the Tomcat <Connector> element was the default configuration, and I never in a million years would have guessed that the Tomcat people would limit their default configuration to IPv6. Commented May 12 at 15:05
  • 1
    I became curious and had to confirm this is indeed in the example connector on /usr/share/tomcat10/etc/web.xml line 105 in tomcat10_10.1.16-1_all.deb for Ubuntu 24.04. However, that is an example and seems to be the only example that has the address attribute set. What a bad luck! Commented May 12 at 15:37

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.