How to add secure websockets to Apache to work with Tomcat on a Self Signed Cert

Took me several hours and a bunch of fiddling to get to the point where Apache would pass thru the websocket to Tomcat and not give SSL handshake error. The setting here will only work on Apach 2.4.47 and above.

Step 1: Create your Certs using java’s keytool:

keytool -genkey -alias tomcat -keyalg RSA -keysize 2048 -validity 3650 -keystore tomcat.jks

THIS IS IMPORTANT!!!
When you run this, the 1st question will ask you what your name is, your name is not the correct answer. Enter:
127.0.0.1
Tomcat’s websocket will run off of some port on 127.0.0.1. If you use something other then the above, you will get SSL handshake errors. Answer the other questions as you please.

Step 2: Take the tomcat.jks file created and move it to the tomcat/conf folder. You will know you are in the right spot when you see server.xml. Make sure you change the permissions to 600 and the owner to whatever tomcat is running under (if you used the lucee installer, it should be lucee).

Step 3: Edit the server.xml file and look for the 1st block that reference port:8443 (it should look like the code block below:

  <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
        	<Certificate certificateKeystoreFile="conf/tomcat.jks"
                         certificateKeystorePassword="ThePasswordUsed"
                         type="RSA" />
        
        </SSLHostConfig>
    </Connector>

Save and restart tomcat.

Step 4: Make sure your Apache HTTPD server has the following modules active:

mod_ssl 
mod_proxy
mod_proxy_http
mod_proxy_wstunnel

Step 5: In the virtual host section for the domain you are going to websocket to, make sure this is entered. And make sure the Proxy Pass for /ws is above the AJP injector. Otherwise, you might spend an hour trying to figure out why Apache is not passing the /ws folder to the backend (don’t ask).

SSLProxyEngine On

ProxyPass /ws wss://127.0.0.1:8443/ws
ProxyPassReverse /ws wss://127.0.0.1:8443/ws

Restart Apache.

Now hit your page with the websocket and it should connect.

However, if you are using websocket snapshot 3.0.0.20-Snapshot, you will get an Connected and an immediate Disconnect, with an error in your websocket log:

"INFO","https-jsse-nio-8443-exec-5","03/27/2026","22:16:09","","websocket-endpoint-factory","Cannot invoke ""lucee.runtime.config.ConfigWeb.getIdentification()"" because ""cw"" is null;onError got involved for component [test2] with session id [0]java.lang.NullPointerException: Cannot invoke ""lucee.runtime.config.ConfigWeb.getIdentification()"" because ""cw"" is null

If you downgrade to the release version, restart Lucee and then upgrade back to the snapshot, restart Lucee, it will work longer, or atleast send you back and empty message. However, once Tomcat is restarted it will give the above error.

1 Like