-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Easier Ability to use Environment Variables in Configuration #1756
Comments
I'm finding that the Regardless, having environment variable support would be huge. I think the client getting the configuration from the server |
I found that the I added some logging to look at configuration and it seems all the way through As a side note, when running in |
I think the problem is This bypasses all the environment and loads config.js directly. You can fix that in a kind of hacky way by creating a "module" in a different location using the configuration in app.get("/config-module/config.js", function (req, res) {
var moduleConfig = "var config = " + JSON.stringify(config) + ";";
moduleConfig += "if (typeof module !== \"undefined\") { module.exports = config; }";
res.type('text/javascript').send(moduleConfig);
}); Then in html = html.replace("#CONFIG_FILE#", "/config-module/config.js"); Or, better, just put the generated module in |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
It appears this is still something that would be helpful. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Would also like this functionality for the same reason as @tillig Could the notification-system be used for this where a LOAD_MODULE-notification is sent on startup that triggers the start()-method on that module. Then the payload could be that modules configuration only with environment-variables populated. And wouldn't it be better with having some kind of templating instead of functions in the config, like: |
In case anyone runs into this and happens to be using @khassel awesome Docker installation, environment variables are supported. .env
docker-compose.yml
config.js.template
|
Thx for the info @daxiang28 Might this be something that should be added to the documentation of the docker project of @khassel ? |
sorry for the late reply ... The construction using variables defined in For replacing variables in Thanks @daxiang28 for the hint that we can combine those 2 features to keep all secrets seperated, I will add a hint to the documentation. |
Maybe OP should re-open this issue since it is not stale. This is still a seriously embarrassing issue to have. As a new magic mirror user I was shocked to see the lack of config sharing and I understand why now...because your config would contain all your secrets! |
Unfortunately, I don't have the ability to re-open the issue, just comment. You'd have to file a new issue. |
Re-opening since some people hav einterest in a solution. Lets discuss :-) |
There was already a solution here #1947 which was not accepted by the repo owner. A very simple solution without breaking changes would be to call |
environment variables suck as a data passing mechanism under linux. and we don't have a launch wrapper like docker compose
|
interested to learn about what alternatives there are and why environment variables are not good. |
This seems fairly hyperbolic considering there are lots of systems that do this, from deploying containers in Kubernetes (where you might pass credentials, etc. in environment) to Java apps that read system settings from environment to simple Node apps that might start listening to a port based on environment. I think it's valid to say that environment variables are painful if they need to be treated as anything other than a string by the consuming code, for sure. Based on context it may be that the environment variable needs to be treated like a number rather than a string, and knowing when to parse that and how to err out or fall back if it fails is a challenge. But I don't know that it means "environment variable suck," it just means there can be complexity. |
in linux, env variables are not passed from x to started app.. UNLESS explicitly 'exported'.. current is
where do you define the variables? for pi0 (only currently) we have a wrapper shell script run-start.sh (to get the server running so u can access via chrome as electron is dead on armv6l).. |
I still think we should have this feature, but have you read the conversation of the not accepted solution? If you can convince @MichMich to accept a solution someone can implement it. |
I still stand by my last comment:
Thoughts? |
The main use case for loading environment variables for configuration is secrets/keys. With this use case in mind I ask the follow; Does the client need to know the api keys ? Is this question module specific ? My understanding of why this feature doesn't exist is because the config.js file is used by the server and client. If the client doesn't need secrets, than I feel this is the problem to be solving since sending secrets that aren't used by the client seems like a security flaw (least privilege) which should be enough motivation to differently implement this config.js file. tl;dr if modules use secrets on the client side I would say this change will require more work than it's worth given the workarounds. |
I want to support @20k-ultra's argument. If I hang a MM in a network, everyone in this network who can access the mirror with a browser can also access the secrets in the |
client means modulename.js, right. it depends. a lot of modules use fetch in browser component (modulename.js) and don't use a node helper. in that case, 'client' needs whatever is required to make the API work. keys, passwords. .... if you use chrome from your pc to access your mirror, then modulename.js is loaded there weather is a perfect example. all client side based and system design sends the config parms to the client side only. the client forwards them on to server side helper |
@KristjanESPERANTO well, it's not 'that' easy. someone would have to know how to find the mm instance, know about dev env, mm structure and where to look. you let people like that on your network? no one I know, that has access to my network, would be able to do that. and there is nothing useful in there. weather calendar, and news. and some other random API keys |
I'm not sure of the exact mechanisms that do this but I refer to client as anything running in a browser.
This is what I mean. Calendar does not need keys in the frontend. This example has access to sensitive information so sending the secrets to anyone on the network that asks for the webpage seems like a flaw in current implementation. For weather, if you get pwned you lose weather API access if someone misuses your tokens but for other modules the risks can be significant. Reminder, I think there is some UX to gain for developers since they wouldn't have to maintain postinstall scripts as suggested above:
If the solution is big enough of a breaking change I understand the hesitation. But, given what I've mentioned (developer UX and security) would MM still have implemented this file in this way ? If the answer is no than we could begin to discuss the best way to fix it. I'm hoping to separate the why and how of this feature so we can more easily discuss in a productive manner. So far I've been talking only about why with responses from those more knowledgeable providing workaround hows. |
I don't think it's a stretch to think people will use magic mirror in a public space. Besides, justifying a security hole because "just don't get pwned" seems silly.
dangerous precedent to set here. How about Alexa integrations ? Not trying to be confrontational btw all! Appreciating the time you've given this. |
the how is a complete rewrite of the core config. the client component would have to ask some server component for 'their' config. today communications is not exposed socket.io communications between front and back. core is not involved other than setup. the helper would have to get info from the core, instead of from the client. this does not protect each modules handling of the config data. every module would be broken. there are also some modules that 'know' that the total config is available in both helper and client, and use that info(my MMM-Config for example, getting the address/ipWhitelist settngs in helper, also count instances of modules, which is not officially available outside my module config) |
side comment, Alexa integrations are dead, thank Amazon... but I know what u meant |
May I write this more than once: I still think we should have this feature ... But I can also understand avoiding breaking changes. May we have to talk about MagicMirror v3 where we do things better and we accept breaking changes. And e.g. realize the idea to load the config from the server. And I want to share my mm with a public url to others without publishing all secrets. |
@khassel I think it would be interesting.. how would you propose to DO it? envsubst and my script do not address your problem. they protect the file system file. |
Correct me if I'm wrong, but we can limit access to the MagicMirror² server to only local host. So in that case no sensitive data is available on the local network. Server only mode is a bit different, but that's what I consider an edge case. If there is a simple non breaking way of solving this, I'm all for it. But we should not complicate things for situations that are considered an edge case and can be solved with an external module. |
the browser side loads the entire config, and separately the portions for each module. in clear text one can use an https connection and then I can transport over the internet to have you view my mirror. but any actor that has access to your browser can see my config. |
Last post was a wish list for a future mm version, its clear that this is not solvable without breaking changes (and therefore I didn't think how I would implement this). Back to current mm version and sum up of the discussion (correct me if I'm wrong):
Possible minimal solution would be the pseudo-envsubst:
As long we have no better idea we can decide to implement such a pseudo-envsubst or close this ticket as not planned. |
correct but point 3, 1st steps |
Got to agree here with the plan, but myabe also some other TODOs I read from here:
The mm2 wasn't build around the idea of protecting senstitive infos in your config (correct me if I am wrong here @MichMich). With the premise of "do not break existing stuff" we cannot change the config-handling for the modules to increase security in v2. There might be modules out there in the wild where you put your banking credentials into the config (or other sensitvie info) but even if this is a "beginner friendly project" people should know a little on security topics. --> so a TODO might be: add a section on security in the documentation website?
Editing the config by hand / copying from the website is a error prone process that might be up for improvement. Thats why I was interested to learn about @sdetweil MMM-Config module. Wouldnt it be nice to have something like that as a new default module? A module for importing / exporting / editing your config? Not something a new user has to download from somewhere else and figure out, but which might help him directly from the beginning with editing his config/mm2 ? --> just a thought, not directly a TODO (only TODO would be opening a new discussion ticket for this :-) |
@rejas did u try the proper url for MMM-Config? |
yes, worked |
This is the implemenation of envsubst discussed in #1756 Documentation update will follow after merge.
## [2.23.0] - 2023-04-04 Thanks to: @angeldeejay, @buxxi, @CarJem, @dariom, @DaveChild, @dWoolridge, @grenagit, @Hirschberger, @KristjanESPERANTO, @MagMar94, @naveensrinivasan, @nfogal, @psieg, @rajniszp, @retroflex, @SkySails and @tomzt. Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not all) of the work on this release as project collaborators. This version would not be there without their effort. Thank you guys! You are awesome! ### Added - Added increments for hourly forecasts in weather module (#2996) - Added tests for hourly weather forecast - Added possibility to ignore MagicMirror repo in updatenotification module - Added Pirate Weather as new weather provider (#3005) - Added possibility to use your own templates in Alert module - Added error message if `<modulename>.js` file is missing in module folder to get a hint in the logs (#2403) - Added possibility to use environment variables in `config.js` (#1756) - Added option `pastDaysCount` to default calendar module to control of how many days past events should be displayed - Added thai language to alert module - Added option `sendNotifications` in clock module (#3056) ### Removed - Removed darksky weather provider - Removed unneeded (and unwanted) '.' after the year in calendar repeatingCountTitle (#2896) ### Updated - Use develop as target branch for dependabot - Update issue template, contributing doc and sample config - The weather modules clearly separates precipitation amount and probability (risk of rain/snow) - This requires all providers that only supports probability to change the config from `showPrecipitationAmount` to `showPrecipitationProbability`. - Update tests for weather and calendar module - Changed updatenotification module for MagicMirror repo only: Send only notifications for `master` if there is a tag on a newer commit - Update dates in Calendar widgets every minute - Cleanup jest coverage for patches - Update `stylelint` dependencies, switch to `stylelint-config-standard` and handle `stylelint` issues, update `main.css` matching new rules - Update Eslint config, add new rule and handle issue - Convert lots of callbacks to async/await - Revise require imports (#3071 and #3072) ### Fixed - Fix wrong day labels in envcanada forecast (#2987) - Fix for missing default class name prefix for customEvents in calendar - Fix electron flashing white screen on startup (#1919) - Fix weathergov provider hourly forecast (#3008) - Fix message display with HTML code into alert module (#2828) - Fix typo in french translation - Yr wind direction is no longer inverted - Fix async node_helper stopping electron start (#2487) - The wind direction arrow now points in the direction the wind is flowing, not into the wind (#3019) - Fix precipitation css styles and rounding value - Fix wrong vertical alignment of calendar title column when wrapEvents is true (#3053) - Fix empty news feed stopping the reload forever - Fix e2e tests (failed after async changes) by running calendar and newsfeed tests last - Lint: Use template literals instead of string concatenation - Fix default alert module to render HTML for title and message - Fix Open-Meteo wind speed units
I've been using Magic Mirror 2.8.0 and want to store secrets (e.g., OpenWeather API keys) outside of my configuration file so I can commit the file to source control. This would also allow for easier Docker image creation where you could poke in some environment variables rather than full config files.
Doing this has been a challenge.
config.js
is used in both a server and a client context. That is, instead of the Electron client app retrieving configuration from the/config
endpoint of the server, theconfig.js
is used directly. This means any references toprocess.env
don't work because...process
doesn't exist by default, and even if you enablenodeIntegration
, the process that Electron is running under isn't the same as the process the server started under. Instead, you need torequire('electron')
and access theelectron.remote.process.env
to get those variables marshaled over. But...nodeIntegration
is off by default. It's also turned off in the main electron.js. This can be overridden by config.There is a discussion where I raised this over in the forum.
A working config.js with environment variables looks like this:
The idea is that you have to fall back from
process
toremote.process
before you can get to the environment.I'd like to propose a couple things that would make environment variable usage easier:
From a backwards compatibility perspective, you could treat config.js as something that both use and the difference would be that the module settings on the Electron side that are read from config.js would be ignored in favor of retrieved settings.
The text was updated successfully, but these errors were encountered: