Search code examples
node.jssslwebsockethttpservernode-https

How can I inject a new SSL cert and key into a running Node http.Server?


I am running a secure websocket proxy to a TCP service. This uses a standard http.Server set up like:

var webserver = http.createServer(                                                                          
    {                                                                                                       
        key: fs.readFileSync(srv.ssl_key),                                                                  
        cert: fs.readFileSync(srv.ssl_cert),                                                                
    },                                                                                                      
    function(request, response) {                                                                           
        response.writeHead(404);                                                                            
        response.end();                                                                                     
    },                                                                                                      
    function(err) {                                                                                         
        srv.log(err);                                                                                       
    }                                                                                                       
);

As you can see, we're already using hilariously undocumented facilities: the options and error handler arguments to http.createServer().

The SSL key and cert are regenerated periodically by LetsEncrypt certbot. When this happens, I would like to inject the new key and cert into the webserver without having to regenerate a new one or reinitialize my websocket.

What further undocumented facility will allow me to do this?


Solution

  • You have to:

    1. Close the current webserver with webserver.close()
    2. Create a new webserver instance with your new key and cert (there's a .setOptions() method on it that you might think you could use to change the key and cert options, but there's no way to get it to generate new TLS credentials after instantiation)
    3. Mount the new webserver on the websocket server with websocketServer.mount(websocketOptions), where websocketOptions.httpServer is your new webserver instance

    This will work nice and smoothly, not interfering with running connections.