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:
-
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.
-
shared libraries loaded by native extension, such as the native
pg-native
package's use oflibpq
, 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.