How to update ENV variables in a Process without restarting it (NodeJS)? - node.js

I have a server running on NodeJS. Is there a way to update the environment variables in the process without restarting the server?
What I'm looking to do is:
Start my server npm start
type something into the console to update ENV variable
Server restarts with new environment variable

From a programmatic standpoint, you should be able to update the process.env variable that was passed into the running process.
For example, running:
cmd_line$: MY_VALUE=some_val node ./index.js
with code:
console.log(process.env.MY_VALUE)
process.env.MY_VALUE = 'some other value'
console.log(process.env.MY_VALUE)
process.env.MY_VALUE = 4
console.log(process.env.MY_VALUE)
output in terminal:
some_val
some other value
4
From a server admin standpoint for an already running application, I don't know the answer to that.

It's possible to debug Node.js process and change global variables:
On *nix, it's possible to enable debugging even if a process wasn't started in debug mode. On Windows, it's possible to debug only processes that were started with node --inspect. This article explains both possibilities in detail.
Obviously, this will work only if environment variables are used directly all the time as process.env.FOO.
If their values are initially used, changing process.env.FOO later may not affect anything:
const FOO = process.env.FOO;
...
console.log(FOO); // it doesn't matter whether process.env.FOO was changed at this point

If you make a change to env variables they will take place immediately only if you make the change via the main Properties dialog for the system which is going to my computer -> Advanced properties -> Environment Variables.
Any program which is already running will not see the changes unless we handle it in the code explicitly.
Logic behind it is that there is an agent which sends a broadcasting a WM_SETTINGCHANGE message and make changes to all applications inorder to notify for that change.

Here's a good explanation on how to setup environment variables in mac OS. Additionally, as others have already answered, you can set them with process.env.ANY_VARIABLE = 'some value'.

I am trying to find a cross-platform answer to this (mac, linux, windows)
For mac, a workaround that I found is using
const shell = require("shelljs");
console.log(shell.exec('launchctl getenv TEST'));
It only works if you set environment variable (e.g. in other terminal tab) using launchctl setenv TEST blahblah

You can try to use this javascript tiny library to update env variables without restarting the node server:
https://www.npmjs.com/package/runtime-node-refresh
Hope this help.

Related

Why is process.env returning an empty object, while process.env.prop returns the prop value?

So I have the simplest example on a node machine running with a react-redux app with webpack (Though I don't think any of this matters for the issue expect it being on nodejs).
Specific calls get a value pack:
console.log(process.env.NODE_ENV); // output: 'development'
General calls get nothing back:
console.log(process.env); // output: {}
What am I missing here?
Addition info the might be relevant:
I am using dotenv for the test environment.
I am using dotenv-webpack for the development environment.
I am not using neither of those for the production environment deployed to Heroku
The problem persists on all environments.
The issue with process.env variable being empty in browser is because browser doesn't have real access to the process of the node.js. It's run inside the browser though.
Usage of process.env.ANYTHING is usually achieved by plugins like https://webpack.js.org/plugins/define-plugin/ which just simply replace any occurrence of process.env.ANYTINHG with env variable during BUILD time. It really does just simple str.replace(/process.env.ANYTING/value/) this needs to be done during build time as once you output dist bundle.js you don't have access to the ENV variables.
Replacing during build time
Therefore you need to be sure that when you are producing production build e.g with yarn build you are using webpack.DefinePlugin and replacing those process.env calls with current ENV values. They can't be injected in runtime.
Injecting in runtime
When you need to access env variables in runtime it's basically impossible in JavaScript in browser. There are some sort of hacks for example for NGINX which can serialize current env variables to the window.ENV variable and in your app you will not use process.env but window.ENV. So you need to either have ENV variables available while you are building the application or build mechanism which will dynamically output current ENV as json to window and access with react. If you are using docker it can be done with ENTRYPOINT otherwise you need some bash script which will always output current ENV variables as JSON to the index.html of your app

Using System environment variables in node / react with docker

I have a react app (CRA) it will be running inside a docker container for which I will set an environment variable "API_KEY" = "some_value". For the example of windows this is System Properties -> Environment Variables -> System Variables -> Variable = "API_KEY" and Value = "some_value".
I would like to access to get this variable into the application at run time. This is for the API_KEY for Azure App Insights.
https://learn.microsoft.com/en-us/azure/application-insights/app-insights-javascript#add-the-sdk-script-to-your-app-or-web-pages
The above link shows the <your instrumentation key>. I will be deploying the same application to multiple environments. Each instance of the application will need to use its specific App Insights. So the goal here is to specify that API_KEY in the environment variables which will be different for each of the docker containers.
Please note I am aware of nodeJs and process.env.API_KEY but this does not read from the systems environment variables. Is there a way to get the system variable to link up to the process.env for the node instance?
-PS this request is to an API service that will need to fire straight away. So making an API request to get it is out of the question. It will be exposed to the end client as it is logging JavaScript events for each client.
The answer is NO. You can not read system environment variables. You can however set process environment variables in a *.env file. In my case I will generate this env file via a shell script which will be triggered by the Dockerfile. This will then scrap the process for it's environment variables that start with "REACT_APP_#".
Hope this helps others.
Generating shell script
https://medium.com/#vietgoeswest/passing-env-variables-from-the-server-to-your-create-react-app-c87578a45358
Setting up env with CRA
https://medium.com/#tacomanator/environments-with-create-react-app-7b645312c09d
Dockerizing a Node.js web app
https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
Passing environment variables from Docker to Node https://medium.com/#felipedutratine/pass-environment-variables-from-docker-to-my-nodejs-or-golang-app-a1f2ddec31f5
Also helpful
https://github.com/facebook/create-react-app/issues/982

Setting up environment variables in node, specifically, GOOGLE_APPLICATION_CREDENTIALS

I have a node application and I'm trying to use the google language api. I want to set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the json file in the same directory (sibling to package.json and app.js).
I had tried process.env.GOOGLE_APPLICATION_CREDENTIALS = "./key.json"; in my app.js file (using express), but it isn't working. I have also tried putting "GOOGLE_APPLICATION_CREDENTIALS":"./key.json" in my package.json and that didn't work as well. It DOES work when I run in the terminal export GOOGLE_APPLICATION_CREDENTIALS="./key".
Here is the error message:
ERROR: Error: Unexpected error while acquiring application default credentials: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information.
Any tips are appreciated, thanks!
After reading and reading about this issue on the internet, the only way to resolve this issue for me was to declare the environment variable for the node execution:
GOOGLE_APPLICATION_CREDENTIALS="./key.json" node index.js
Because I was able to print the token from my server console, but when I was running the node application, the library was unable to retrieve the system environment value, but setting the variable for the execution, it was able to retrieve the value.
It could be that the environment variable in your OS was not accurately set. For example in Linux you usually have to set GOOGLE_APPLICATION_CREDENTIALS in the terminal where you executed your app.
export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
Another option you have is passing the json path by code. It is documented this process using Node.js with the Cloud Storage.
Just to update this thread.
Relative paths with GOOGLE_APPLICATION_CREDENTIALS now works fine with dotenv :)
Just store your service-account credentials as a file in your project and reference it relative to your env-file as a path. Then it should work fine :)
I encountered the same issue. I was able to get it working by doing the following:
export GOOGLE_APPLICATION_CREDENTIALS="//Users/username/projects/projectname/the.json"
The issue is covered mostly in the docs here.
the command varies slightly depending on what your OS is:
The GOOGLE_APPLICATION_DEFAULT environment variable you are setting is accessed by the google client libraries - it wont work with a relative path, you'll need to set the absolute path.

Shim config not supported in Node, may or may not work

I am working on a project which works fine on browser , now we are trying to run it on server side using nodejs.
I have below configurations :
node : v4.2.1
npm : v2.14.7
and when I am trying to run my project on nodejs , getting the error as :
Shim config not supported in Node, may or may not work
Since the modules and dependencies (AMD) are working fine on browser I assume the shims config are correct .
Please let me know if I am missing something ?
https://github.com/jrburke/requirejs/issues/1443
Regards
Manish
Since the modules and dependencies (AMD) are working fine on browser I assume the shims config are correct .
That's an incorrect assumption. The problem is that Node.js operates with a set of basic assumptions that are very different from how browsers work. Consider this statement:
var foo = "something";
If you execute this at the top of your scope in Node.js, you've created a variable which is local to the file Node is executing. If you really want to make it global, then you have to explicitly shove it into global.
Now, put the same statement at the top of the scope of a script you load in a browser with the script element. The same statement creates a global variable. (The variable is global whether or not var is present.)
RequireJS' shim configuration is used for scripts that expect the second behavior. They expect a) that anything they declare at the top of their scope is leaked to the global space and b) that anything that has been leaked to the global space by scripts they depend on is available in the global space. Both expectations are almost always false in Node. (It would not be impossible for a module designed for node to manipulate global but that's very rare.)
The author of RequireJS explained in this issue report that he does not see it advisable for RequireJS to try to replicate the browser behavior in Node. I agree with him. If you want to run front-end code in the back-end you should replace those modules that need shim in the browser with modules that are designed to run in Node.

Change configuration in runtime by changing environment variables using the module node-config

I'm trying to use the node-config module to change some parameters of my configuration (basically logging level) during runtime.
In the official documentation says:
Environment variables can be used to override file configurations. Any environment variable that starts with $CONFIG_ is set into the CONFIG object.
I've checked that this is true when the server starts but it does not seem to work once it's up. (The handler of the watch function is never called when an environment variable is changed unlike a change in the runtime.json file or directly changing a config variable).
I'm currently watching the whole CONFIG object like this:
var CONFIG = require('config');
CONFIG.watch( CONFIG , null , function(object, propertyName, priorValue, newValue){
console.log("Configuration change detected");
});
Does anyone know if this is possible?
The environment is available during startup of a process.
If the process is running, you won't be able to change the environment anymore, the process is in.
The only option is to restart the process or use other mechanisms to communicate with it.
Say for example having a rest or tcp listener inside, where you can transfer your variable inside.
Best regards
Robert
As you must knowing, React is a single page application which is eventually when it is complied is a static page app that means all the files of the react application is complied into vanilla JS and CSS file bundle in a Tarball. Now that Tarball is eventually deployed on a web server. It could be Apache web server, nginx web server or anything which you are using it but an important point is the static app is running in someone else browser and someone access to website CSS and JS are downloaded in a browser and it is running in the browser runtime environment so technically you cannot have a runtime environment variable for someone else browser but may be there would be a way to access them during runtime.
SOLUTION
I have achieved this goal with the package called runtime-cra.
follow the steps on this official documentation: https://blog.risingstack.com/create-react-app-runtime-env-cra/

Resources