Cumulus4j can be used in 2 different deployment scenarios. But before we explain them, here's the normal deployment scenario (without Cumulus4j) that you're already used to:
Usually, you deploy the back-end of your application to your application server (e.g. Jetty, Tomcat, Glassfish, JBoss, or whatever you like). If your client is a browser, you're already done. If your client is a rich client (aka. fat client), you additionally deploy the front-end to your client-computer(s).
As indicated by the cyan arrow, the connection (usually a TCP/IP-based protocol like HTTP, HTTPS, RMI etc.) will be initiated by the client. Requests are then sent from the client to the server, while the server's response goes the opposite way.
2-computer-scenario (without key-server)
If you add Cumulus4j to the picture, your back-end will additionally contain a Cumulus4j REST-based API and your client communicates in parallel with this API to allow for key management:
The second communication channel is (as indicated by the yellow arrow) initiated by the client, too, and should thus not lead to any firewall problem.
The requests, however, are sent from the server to the client inside the existing connection. These key requests happen whenever the server has to encrypt or decrypt data and therefore needs access to certain keys.
3-computer-scenario (with key-server)
Alternatively to holding the keys on every client, it is possible to run a separate key-server:
This key-server could be located in your company's private LAN, for example, or somewhere in the internet, but separated from the application servers (e.g. another cloud or a hosting provider).
Which modules need to be deployed where is documented in the module-location-matrix.
It is important to understand that the application server usually is not one single machine, but a cluster. Especially when using the cloud, the application server might be distributed over an unknown number of physical machines (cluster-nodes).
Therefore, it can happen (and is even very likely!) that the two connections arrive on separate cluster-nodes, like shown in this example:
Therefore, the original key request (1) must be sent to the cluster-node having a direct connection with the key-manager, first. Then, this other cluster-node forwards the key request (2) to the key-manager and after receiving the response (3) it finally forwards that response to the original requestor (4).
The handling of this complete process is done by implementations of MessageBroker.