Support for .env files? or other ways to store and load secrets?

Got node red in docker using a project folder with git version control. Now I need to store credentials (when flows connect via API to other servers).

One normal way of doing this is having local .env files which are in gitignore list so not shared.

How to do this in node red? Any way to use .env files, or other alternatives?

How does Docker start and stop Node-red?

Node-red itself, for well designed nodes, stores credentials in flows_cred.json and they are not included in an export of the flow[s].

If you start Node-red using systemd, it will import environment variables declared in ~/.node-red/environment or ~/.node-red/EnvironmentFile (the filename is specified in the systemd script)

I presume the values of these environment variables are not exported.

You can set variables per flow too, I'm not sure if these are exported.

And you can use the first editor tab to define secrets as global context variables, which won't be exported unless you export all flows.

Found the source of node red in docker and made some minor modifications:
node-red/node-red-docker: Repository for all things Node-RED and Docker related (github.com)
Running under Docker : Node-RED (nodered.org)

Start by running the docker build script to make the image. Then docker run to create and run container. The one which exposes /data folder as bind mount. It exposes a few of the important parts like flows.json, package.json etc. But not the "environment" file so have to look for that one inside the container and see if I can expose it through /data bind mount. This is the way I made the project folder for git repo to get version control.

While the credentials is nice, the password is still stored in settings.js which is in the same location in git repo, so no point having it there at the moment. I was thinking about having the env file on gitignore and store it in a separate vault instead. That seems to be a common way of handling secrets in projects, unlike the creds file node red uses.

It doesn't have to be there. settings.js is a javascript file, you can use code there to pick the secret up from the environment or anywhere you like.

Ok, but how then can I add environment file? Tried adding "environment" file to home location of node red, which seems to be /usr/src/node-red so added file /usr/src/node-red/environment but it isn't picked up after restart. Should I instead piggyback on settings.js to link to another env file? How do I handle secrets in node red? At the moment it's stored in plain text in src code.

I don't know about Docker, but looking at the docs I see that it describes how to set environment variables.

That moves the secrets to commandline args. So then I can't simply have the docker run command in readme anymore. Instead of a private env file, I have a private readme file? And that gets cumbersome with multiple secrets. Each have to be synced between settings.js and commandline.

All I want is to add a simple .env files with secrets to be automatically loaded as environment variables. This is possible with virtually all node projects, but not node red?

I managed to find one way of doing it with pure js as proposed earlier.

In settings.js, added

const secrets= require('./env.json');
process.env.SECRET = JSON.stringify(SECRET);

Now, in any function node in node red, I can write:

msg.secret = JSON.parse(env.get("SECRET"));

It's not pretty, but it gets the job done. Is this the easiest way of having secrets in a separate env file in node red?

Edit: Slightly cleaner version:

const secrets= require('./env.json');
for(const key in secrets){
  process.env[key] = secrets[key];
}

Which can now be called as any other env variable:

msg.password = env.get("secretPassword");

It's a dirty hack but I'll keep it until I find something easier.

As I said, I don't know much about docker, but a bit of googling suggests that can pass the env vars from a file to a docker container using something like
docker run --env-file ./env.list ...

1 Like

That's good, but still every variable would have to be individually hardcoded in setting.js?

Ie. this part in node red settings.js:

module.exports = {
  credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET // add exactly this
}

credentialSecret is a special case. All other env vars you pass in can be accessed directly by name direct from the flows. See Using environment variables : Node-RED

credentialSecret is used by node red to encrypt credentials file?

Read what it says about credentialSecret in settings.js

/** By default, credentials are encrypted in storage using a generated key. To
     * specify your own secret, set the following property.
     * If you want to disable encryption of credentials, set this property to false.
     * Note: once you set this property, do not change it - doing so will prevent
     * node-red from being able to decrypt your existing credentials and they will be
     * lost.
     */

Sounds like node red is doing its own key vault thing.

Of course.

Thanks! Not sure way to go for me is to let each project to have their own key vaults...