NODE_OPTIONS has landed in 8.x!
NODE_OPTIONS environment variable is available in 8.0.0, see the 8.x docs. It should land soon in a 6.x minor (most likely 6.12.0) to be available for production deployments.
NODE_OPTIONS allows command line arguments that make sense (not
-e, for example) to be provided though an environment variable. As an environment variable, it can be specified without actually modifying any scripts that run node, and it affects all processes that inherit the environment, particularly node child processes.
An example of when its not possible to control the node invocation arguments are
npm install scripts. If you were tearing your hair out trying to figure out why a sub-dependency script is failing during
npm install but not when you run it standalone, you could try:
% npm i -g node-report % NODE_OPTIONS="--require /usr/local/lib/node_modules/node-report" \ npm i some-project
Note that I need to have
node-report installed somewhere and specify a fully-qualified path to it, since its not a dependency of
Once #13932 lands, this will also be possible:
% NODE_OPTIONS=--abort-on-uncaught-exception npm install some-project
While useful for local debugging,
--abort-on-uncaught-exception is also an excellent troubleshooting tool for production deployments, and causing node to generate a core file on failure is a production best-practice. (See Exploring Core Dumps for information on how to use core files for post-mortem debugging.) Despite this, most clouds run node applications with
npm start (there is no other common convention for running node applications, unfortunately), and most
start scripts are written by developers without considering how the app should be run by in production.
NODE_OPTIONS allows the DevOps responsible for production to control these aspects of the runtime so that developers don’t need to.
Here’s some background on why configuration by environment, and
NODE_OPTIONS in particular, is so useful.
Node has a number of runtime configuration options, and they have 3 ways of being specified:
- compiled-in configuration
- environment variables
- command line options
Of these, build configuration is the least flexible, it can only be used if you compile node yourself. Its a good mechanism for Linux distributions, for example, that build node themselves, and want node to link against the system OpenSSL libraries (
--shared-openssl) and to use the system CA store (
Build configuration is not a good mechanism for anything that an end user might want to control. For that, we need to use environment variables or command line options.
Whether to use one or the other is always a problematic choice, as can be seen by looking at the
node --help output. The current state is a bit of a mixed bag, some options are only available by modifying the node command line (
--tls-cipher-suites), some only by modifying the environment (
NODE_EXTRA_CA_CERTS), and some are available in both (
There is a case to be made that all options should be available both via environment variable and command line option, but this can lead to a lot of duplication. There are over well over 400 options supported by the node command line at the moment, exposing each as an environment variable is not reasonable.
There is another approach, to instead expose options through the CLI, and have a single environment variable that can be used to provide CLI options. This is a common feature in scripting languages (
PERL5OPT). With this pattern, all options can be specified either via environment variable (without having to invent a new environment variable specific to the option), on the command line, or both (command line will take precedence over the environment).
This approach is now available via the
NODE_OPTIONS environment variable.
I’m pretty excited about this, because while a command line argument is the most convenient way to specify options for users working at a terminal prompt, it can be quite difficult to find and modify the command line invocation in production. They are often hard-coded into
package.json scripts, or templates for generating systemd files. This can make it very onerous to uniformally control important features such as the trused CA roots or default cipher suites in production. Also, container based systems favour immutable containers and configuration via environment variable, so having to modify a container to change command line options can be very difficult. Environment variables are also a powerful way of setting defaults globally, because they are inherited by child processes. They can be set machine/image wide, per-user, per command invocation (along with all the child processes of that command).
NODE_OPTIONS is not perfect, do to some nervousness this first version has gone with a whitelist approach which requires any command line option allowed in the environment to be explicitly listed in the node source. In particular, notice that most V8 flags are not permitted. We may change this to a blacklist at some point, but in the meantime if any V8 command line option you want is not supported please raise an issue on the node issue tracker and we should be able to get it supported.