Fix Node.js OpenSSL issues on Heroku-22

Issue

When running Node.js 16 or lower on the Heroku-22 stack, OpenSSL errors may be observed, such as:

  • certificate could not be obtained
  • no SSL error reported
  • FATAL: no pg_hba.conf entry for host "REDACTED", user: "REDACTED", database: "REDACTED", no encryption
  • error:25066067:DSO support routines:dlfcn_load:could not load the shared library

Resolution

This issue arises from Node.js versions 16 and older statically linking against OpenSSL version 1, running on a system that uses OpenSSL version 3. Ubuntu 22.04 (which Heroku-22 is based on) uses OpenSSL version 3.

The recommended solution in both cases is to update an affected app's Node.js runtime to version 18.x, which statically links against OpenSSL 3. This can be achieved using 18.x as the version definition for key node in the engine section of package.json, as documented in the Node.js Support Dev Center article. In some cases, it may be sufficient to update to the latest Node.js 14.x or 16.x point releases.

Generally, a version should not be specified exactly to ensure the latest releases are always picked up during a build. For example, to always use the latest Node.js 18.x release, the node key in the engines section of package.json should look like this:

"engines": {
  "node": "18.x"
}

Two specific types of malfunction can arise from this difference in OpenSSL versions between the system and the Node.js runtime:

  1. Node.js reading the system-wide /etc/ssl/openssl.cnf configuration file during startup can can cause the OpenSSL 1 routines compiled into older Node.js versions to misbehave due to certain OpenSSL 3 specific sections in that configuration file.

    The solution is to update the Node.js runtimes to at least versions 14.14 or 16.16. No workaround exists for Node.js versions 12 and older, which are EOL.

  2. shared libraries loaded by native extension, such as the native pg-native package's use of libpq, will cause conflicts if the shared library, which on Heroku-22 dynamically links against OpenSSL 3, is loaded into a Node.js that is statically linked against OpenSSL 1.

    The solution is to update the Node.js runtimes to version 18. No workaround exists for older Node.js versions, as they statically link against OpenSSL 1.

If a Node.js version upgrade isn't possible, the recommended solution is to revert the app to the Heroku-20 stack. This can be done by setting the stack using heroku stack:set heroku-20 -a myapp, and then deploying a change.

Ask on Stack Overflow

Engage with a community of passionate experts to get the answers you need

Ask on Stack Overflow

Heroku Support

Create a support ticket and our support experts will get back to you

Contact Heroku Support