typescriptsslmosquittomqtt.js

MQTT.js does not accept certificate chain


I try to secure-connect to mosquitto with MQTT.js (https://www.npmjs.com/package/mqtt) and I always get the following error:

node.js

Error: self-signed certificate in certificate chain
    at TLSSocket.onConnectSecure (node:_tls_wrap:1677:34)
    at TLSSocket.emit (node:events:518:28)
    at TLSSocket._finishInit (node:_tls_wrap:1076:8)
    at ssl.onhandshakedone (node:_tls_wrap:862:12) {
  code: 'SELF_SIGNED_CERT_IN_CHAIN'
}

mosquitto

1749810067: New connection from 127.0.0.1:52519 on port 8883.
1749810067: OpenSSL Error[0]: error:0A000126:SSL routines::unexpected eof while reading
1749810067: Client <unknown> disconnected: protocol error.

It is somehow clear that there's a self-signed certificate in the chain - the root-CA - so I find that error message weird...

Maybe I understand something wrong?

I created a own certificate chain which I also verified via openSSL. Also two-way TLS connecting using MQTTX (https://mqttx.app/) works without any problem so I guess my certificates + chain is fine.

Configuration

Certificate-chain structure

Verified with openSSL and working great when using MQTTX.

mosquitto.conf

For mosquitto I combined the intermediate.crt and the ca.crt to one ca_all.crt.

listener 8883
protocol mqtt    
cafile ca_all.crt
certfile server.crt
keyfile server.key
allow_anonymous true
require_certificate true

MQTT.js

this._mqttClient = await mqtt.connectAsync(
  'mqtts://localhost:8883',
  {
    protocol: 'mqtts',
    caPaths: 'ca_all.crt',
    certPath: 'client.crt',
    keyPath: 'client.key',
  });

What I already tried

I'm happy for every hint which could make this work! Thanks in advance.

2025-06-16 Update

Similar issue nodejs - error self signed certificate in certificate chain

This issue seems to be similar but the solutions are not applicable for my use case.

2025-06-16 Solution

The files must be read and then passed to ca, cert and key of the options.


Solution

  • NodeJS does not take paths to certificates or keys, you need to pass the actual content e.g.

    const { readFileSync } = require('node:fs');
    
    this._mqttClient = await mqtt.connectAsync(
      'mqtts://localhost:8883',
      {
        protocol: 'mqtts',
        ca: [readFileSync('ca_all.crt')],
        cert: readFileSync('client.crt'),
        key: readFileSync('client.key'),
      });
    

    Also NODE_EXTRA_CA_CERTS needs to be a Environment variable in scope for the process, it is only read once at startup, so you can not set it using process.env.NODE_EXTRA_CA_CERTS='/path/to/file.crt'