Reverse Proxy and Load Balancer Requirements

Assumptions

  • The context path of Cadenza Web (usually /cadenza/) is the same, both externally and internally. It is not trivial to operate Cadenza Web with different context paths and we strongly discourage users to do that.

General Requirements for all Implementations

This section describes the generic configuration required for any HTTP reverse proxy you want to use with Cadenza Web. The basic idea is to transport the external website details (protocol, hostname and port) to Cadenza Web using HTTP headers and then to configure Cadenza Web’s Tomcat to make use of these HTTP headers.

Support for Session Stickiness with Cookies

Since Cadenza Web stores information in the session on the server, it is essential that all client requests are being served by the same instance of Cadenza Web. This is usually done by configuring session stickiness through cookies, so the load balancer can decide which instance of Cadenza is the correct one to handle subsequent requests. Depending on the implementation, this can be done by reusing the existing JSESSIONID or by creating a new cookie (Using nginx as load balancer in Kubernetes requires this mode).

Headers

Specifically the following headers should be set on each incoming request to Cadenza Web:

Header Explanation Example

Host

Hostname and port of the original request

Host: www.example.com:9999

X-Forwarded-Host

Alternative to Host: if the reverse proxy does not or can not set the external hostname in the Host header, then it is also possible to use the X-Forwarded-Host header. This must only be used if Host does not contain the external address.

This is not read by default by Tomcat and needs to be configured in the RemoteIpValve. [1]

X-Forwarded-Host: id42.example-cdn.com

X-Forwarded-Proto

This is the external protocol used for the request: the value is either http or https.

This is not read by default by Tomcat and needs to be configured in the RemoteIpValve [1]

X-Forwarded-Proto: https

X-Forwarded-Port

Contains the external port number used for the request: the value is an integer value between 0 and 65535

This is not read by default by Tomcat and needs to be configured in the RemoteIpValve [1]

X-Forwarded-Port: 9999

If you use a reverse proxy in front of a Kubernetes ingress controller which servers the content under a different hostname than the ingress resource you have to ensure that Cadenza receives the correct value for the headers Host and X-Forwarded-Host. The ingress controller decides based on the value for Host which ingress resource will be used. Depending on the product used for the ingress controller there are different ways to deal with this situation. If you are using nginx as ingress controller you must add the annotation nginx.ingress.kubernetes.io/upstream-vhost to the host name which is used by the external reverse proxy, otherwise Cadenza will not be able to build its own URLs correctly.

Adjust Maximum Upload Size

It might be necessary to adjust the maximum file upload size settings in the reverse proxy. The error you will get otherwise when uploading files is HTTP 413 - Request Entity Too Large. The following table lists default values and examples for the configuration of the different reverse proxy products.

ReverseProxy Default Upload Size Parameter Name Documentation

Apache httpd

1 GB

LimitRequestBody

Apache documentation

nginx

1 MB

client_max_body_size

nginx documentation

HAProxy

Unlimited (although you may run into timeouts)

N/A

N/A

Server Sent Events and Response Buffers

Cadenza uses Server Sent Events (SSE) for communication from the server to the client whenever we do a long-running process in the backend that needs to report progress to the frontend. For example the uploading or exporting of an Excel file. SSE is a standard HTML5 feature that has been supported in browsers since 2008.

Some servers acting as reverse proxies either block the responses or buffer those responses which causes these operations to fail. Firewalls and reverse proxies used have to support SSE. This is usually the case, but certain configurations or content based filtering can cause these SSE requests to fail.

Azure Application Gateway

The Azure Application Gateway has a response buffer to accommodate slow clients. The effect with SSE is that these are collected by the application gateway and are only delivered after approx. 2 minutes. To users it seems as if Cadenza did nothing for about 2 minutes and then suddenly a file download (for example) appears.

Unfortunately, the response buffer cannot be configured beyond a simple "on/off". Therefore, the recommendation is to deactivate the response buffer.

Example Configuration for Commonly Used Products

We have collected more information and example code snippets for the most commonly used products, Apache, NGINX and HAProxy.

TLS Configuration

Please be aware that TLS (often still called SSL) configurations for reverse proxies and load balancing can widley vary based on the products and infrastructure in use. Thus, we cannot provide example configurations. The Mozilla Foundation however, provides a free SSL Configuration Generator that can be used to create configuration files for widely used server software.


1. The Cadenza distribution and docker container are delivered with an appropriately configured RemoteIpValve in the Tomcat server.xml. If you use your own Tomcat installation you need to configure this Valve yourself as a child element of the relevant <Context> element: <Valve className="org.apache.catalina.valves.RemoteIpValve" internalProxies=".*" protocolHeader="X-Forwarded-Proto" portHeader="X-Forwarded-Port"/>.