Change ENV variables at runtime - node.js

Is it possible to inject/change the current enviroment variables in an already loaded and started NodeJS process?
Exposing an Interface within the application is not an option, restarting is also not a valid option.
The process is running inside a docker container, requiring a specific NodeJS Version is possible.
EDIT: The change must be done from outside the application source so doing process.env.ENV_VAR = "new env" is not possible.

It isn't possible to modify the env vars of a running process. This isn't unique to NodeJS processes. It's just how env vars work on UNIX like operating systems. The vars live within the address space of the process. And while they are, typically, initially placed at a well known location near the top of the stack the current vars are likely to be at an arbitrary address in the heap. Env vars are intentionally private to each process. So unless the program provides an API for changing its env vars you can't modify them once the program is running.

You should use a redis store shared between containers that has stored the env.
redis node repo - redis listen for changes

Related

Is it possible to set the system proxy from golang app in macOS or Linux distributes?

I'm creating golang app with a proxy server as a pet project, and I want to have the possibility to set himself as a system proxy. Is it possible? And how?
Proxies are often configured through the HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables. In Unix-style operating systems, these variables are inherited from the parent process to its child processes.
This being said:
your program can modify its own environment and start other processes as child processes (passing in the _PROXY variables).
your program may modify the shell startup scripts (like .bashrc, .cshrc), and a newly started shell will pick the values up and pass them to newly started processes.
But I am not aware that modifying the environment of other (active) processes is possible.

Node.js: How to read variables from the system?

I'm completely newbie with Docker and to make a deploy in production I need to read the "environment" variables instead of a file or instead of the package.json script line from the operating system of the container.
I know how to read variables from a .env file or from the script line but I don't know how to do it from the system and I don't know if its possible to read these variables from the system.
How can I do that? Is it possible?
The process doesn't change. You still use the below to read environment variables that the process is running in. Reference for Node.
const envVariable = process.env.NAME_OF_VARIABLE;
Setting the variable in a Dockerfile can be done using the below. Docs for this are here.
ENV <key>=<value> ...
Things get more complicated when using things like LXC or Kubernetes though.

Correct usage of ENV in distributed Node system

I am building a relatively complex distributed Node system. Let's say there are two processes (node apps), A and B. They are defined in separate projects.
In addition, there are a couple of custom made node modules, being used in both A and B. Let's call them M and N. In addition, M is using N.
How should I correctly handle environment vars?
I guess I should define .env for both main processes (A and B), handle all ENV vars from there and simply pass the needed env vars from there, down to M and N. This way, M and N (and other internal modules) will receive their own ENV vars passed as parameters on creation.
Is this approach correct?
Having modules getting direct access to process.env is not a good idea, and modules having their own .env file is an even worse idea.
.env files should not be added to source control (ie git) because they change with the environment (dev, prod, pre-prod) and sometimes contains sensitive information (like AWS secret keys). So that would require you to paste a .env file each time you install your node_modules making your deployment process more complex.
The .env file loaded inside your module could merge in unexpected ways with the .env of your root app (remember there is only one process.env).
Imagine a case where your module would need to behave differently in two parts of your application. How would you override the data loaded via the .env file only in one place?
So in my opinion, your guess is correct: don't put .env in node_modules.
// This is better...
nModule.someMethod(process.env.PARAM1, process.env.PARAM2);
// ...than this
process.env.PARAM1 = '';
process.env.PARAM2 = '';
nModule.someMethod();
I feel strongly that environment variables are reserved for, well, the environment. This to me implies a few things:
Inside the code, these variables should be global, i.e., accessed only via process.env.
They are not passed down to other modules. Certainly it's a good idea to make dependencies customizable with parameters you can pass to the functions they export. But the environment should not be used for that.
How you load values into process.env is really a question of how you start your programs A and B. I personally prefer systemd services for that which have excellent support for defining the runtime environment. The dotenv package seems more like a crutch, but it's fine from the program's perspective.
Your approach sounds correct and it should work. When you define .env file and use dotenv package, you will be able to access all the variables inside .env in your code. That means that custom made node modules will also be able to access it, and you don't have to pass them anything (you can access them directly with process.env.NAME_OF_ENVIRONMENT_VARIABLE).
SUMERIZE: Create .env file in both A and B, use dotenv package, and then you can access environment variables directly inside the code with process.env.NAME_OF_ENVIRONMENT_VARIABLE (in custom node modules also). You can create constructor (for custom modules) in modules A and B, and just pass process.env.ENV_WHATEVER as a parameters. That is even better approach since your custom module's logic will be independent from the rest of the app (it will depend only on the input).
NOTE: Don't commit your .env to Git since .env usually have some confidential information. The best practice is to create a .gitignore file and add .env in it.
RECOMMENDATION You can keep all your .env files in one centralized place for better management. You can check some password management tools like https://www.dashlane.com/ or https://www.lastpass.com/.
You mentioned complex distributed system. Distribution can also be associated with a hub / centralized key/variable management system. I'm assuming there are many env variables that are shared across your multiple apps.
Isn't it a plus if you create a centralized node that contain all your required variables and protected them with authentication?
All nodes (regardless of app) to maintain only a single password string in order to authenticated with the centralized node, and load all required variables from a single .env file.
Alternatively you can use a system like vault

Env Variables in NodeJS

I'm new to NodeJS and trying to understand the internal working of the system. Normally we create a .env file or some other configuration file to keep and manage secrets. The same environment values can be kept at the system level like using "export" command on mac.
what I'm trying to understand is how NodeJS loads and reads these value when we start the program either from a configuration file or from system itself.
You can dig through the NodeJS source code to actually see how the environment is provided to NodeJS, e.g. here through the RealEnvStore class. As you can see uv_os_getenv abstracts access to the env depending on the actual operation system.
At least on unix systems uv_os_getenv uses the environ variable which basically references all the environment variables that are made available to the node process as you can see here.

How to run Linux/Ubuntu commands(not executables) from Nodejs

I have been running executables using spawn in nodejs all this while, now when i am trying to use spawn to run ubuntu commands like unset, export etc, they dont seem to work. I guess cause it is looking for executables.
I even tried exec, that does not seem to work too. Any tips?
I have an ubuntu device running node, from the UI i need to set/unset env variables for proxy, e.g. http_proxy and no_proxy. Apart from export what other way can i do it via node? The env variables should be set system wide not just for the current process.
Environment variables only exist in memory and are local to a process. For any running process, only the process itself can make changes to the set of environment variables "belonging" to that process, but those changes will not propagate to existing child or parent processes.
In short: you cannot change an environment variable that will apply to all processes on your system (not even from a regular shell).
You can only set an environment variable so it becomes available for newly created child processes (child processes by default inherit the set of environment variables from their parent), but that's about it.
If you have control over how the processes that require those specific environment variables are started, you could write the value for those variables to a file (from Node) and source that file right before the other processes are started, but it really depends on the actual use case whether this is a usable option.

Resources