Putting Apache HTTP Server in front of Tomcat lets a Java web application answer on a normal site hostname while the Tomcat connector stays on an internal port. The public virtual host can handle TLS, logs, compression, and access policy before forwarding only the application paths that belong to Tomcat.

Apache uses mod_proxy and mod_proxy_http to pass HTTP requests to the backend connector. ProxyPass sends the matching public path to Tomcat, ProxyPassReverse rewrites backend redirect headers, and ProxyPreserveHost can pass the public Host header to the application.

Keep the public path and the Tomcat context path aligned unless the application was designed for a different external path. The examples below use the Debian and Ubuntu Apache layout with /etc/apache2, apache2ctl, and the apache2 service; on Red Hat-style systems, use the matching /etc/httpd path, apachectl command, and httpd service name.

Steps to configure Apache as a reverse proxy for Tomcat:

  1. Confirm the Tomcat application answers from the Apache host.
    $ curl -isS http://127.0.0.1:8080/
    HTTP/1.1 200
    Content-Type: text/html
    Content-Length: 38
    
    Tomcat backend reached through Apache

    Run this check on the server that will run Apache. A Tomcat URL that works from a workstation can still be blocked from the reverse proxy host by a listener, firewall, or bind-address setting.

  2. Enable the Apache proxy modules.
    $ sudo a2enmod proxy proxy_http
    Enabling module proxy.
    Considering dependency proxy for proxy_http:
    Module proxy already enabled
    Enabling module proxy_http.
    To activate the new configuration, you need to run:
      service apache2 restart

    proxy and proxy_http perform the HTTP backend handoff from Apache to Tomcat.

  3. Create a virtual host file for the public Tomcat hostname.
    $ sudoedit /etc/apache2/sites-available/app.conf

    Use a short file name tied to the public application name so later operators can identify the proxy vhost from /etc/apache2/sites-available without opening every file.

  4. Add the Apache-to-Tomcat proxy mapping.
    <VirtualHost *:80>
        ServerName app.example.net
     
        ProxyRequests Off
        ProxyPreserveHost On
     
        ProxyPass        "/" "http://127.0.0.1:8080/"
        ProxyPassReverse "/" "http://127.0.0.1:8080/"
     
        ErrorLog ${APACHE_LOG_DIR}/app.error.log
        CustomLog ${APACHE_LOG_DIR}/app.access.log combined
    </VirtualHost>

    Keep the same trailing slash style on both sides of each mapping. For a context path such as /inventory/, use that path on both the public and backend side instead of hiding a different Tomcat context behind Apache.

    Do not turn ProxyRequests on for this reverse proxy. Forward proxy mode can let clients use the server to reach arbitrary external sites.

  5. Set Tomcat connector proxy attributes in /etc/tomcat10/server.xml when the application builds absolute redirects from servlet request data.
    <Connector
        port="8080"
        protocol="HTTP/1.1"
        connectionTimeout="20000"
        proxyName="app.example.net"
        proxyPort="80"
        scheme="http" />

    For an HTTPS public virtual host, use proxyPort="443", scheme="https", and secure="true". For multiple public hostnames or client-IP-sensitive controls, configure a trusted forwarded-header path instead. Related: How to configure RemoteIpValve in Tomcat

  6. Enable the Tomcat proxy site.
    $ sudo a2ensite app.conf
    Enabling site app.
    To activate the new configuration, you need to run:
      service apache2 reload

    Disable 000-default.conf if it would otherwise answer unmatched requests on the same listener.

  7. Test the Apache configuration syntax.
    $ sudo apache2ctl -t
    Syntax OK

    If AH00558 appears before Syntax OK on a fresh host, Apache is warning about a missing global ServerName. Fix that warning separately, but Syntax OK means this vhost file parsed successfully.

  8. Restart Tomcat if /etc/tomcat10/server.xml changed.
    $ sudo systemctl restart tomcat10

    Skip this restart when the Apache vhost was the only file changed.

  9. Reload Apache to apply the enabled proxy virtual host.
    $ sudo systemctl reload apache2

    Use sudo systemctl reload httpd on Red Hat-style systems when Apache runs under the httpd unit.

  10. Request the public Apache URL and confirm the response comes through the proxy.
    $ curl -isS http://app.example.net/
    HTTP/1.1 200
    Date: Wed, 10 Jun 2026 20:57:50 GMT
    Server: Apache/2.4.66 (Ubuntu)
    Content-Type: text/html
    Content-Length: 38
    
    Tomcat backend reached through Apache

    The Server header shows Apache answered the client-facing request, while the body should match the Tomcat application endpoint.

  11. Check the Apache virtual host access log for the proxied request.
    $ sudo cat /var/log/apache2/app.access.log
    203.0.113.25 - - [10/Jun/2026:20:57:50 +0000] "GET / HTTP/1.1" 200 265 "-" "curl/8.18.0"

    If you also need Tomcat-side request rows for backend timing or client-IP verification, enable and review a Tomcat AccessLogValve for the application host. Related: How to enable Tomcat access logs