Meteor 1.3 and configuration - node.js

i have a simple question.
When you use node + webpack you can easily configure whatever you want.
For example i can write in config default path for my app modules.
Haw can i do it in Meteor 1.3? do they have some config file such Webpack?

Meteor applications can store configuration options like API keys or global settings. An easy way to provide this configuration is with a settings.json file in the root of your Meteor application. The key/value pairs are available only on the server, but you can provide public access to settings by using public:
settings.json
{
"privateKey": "privateValue",
"public": {
"publicKey": "publicValue"
}
}
These values are available in your app using Meteor.settings.
From the Full Meteor Docs:
Meteor.settings contains deployment-specific configuration options. You can initialize settings by passing the --settings option (which takes the name of a file containing JSON data) to meteor run or meteor deploy. When running your server directly (e.g. from a bundle), you instead specify settings by putting the JSON directly into the METEOR_SETTINGS environment variable. If the settings object contains a key named public, then Meteor.settings.public will be available on the client as well as the server. All other properties of Meteor.settings are only defined on the server. You can rely on Meteor.settings and Meteor.settings.public being defined objects (not undefined) on both client and server even if there are no settings specified. Changes to Meteor.settings.public at runtime will be picked up by new client connections.
A good write-up can also be found on TheMeteorChef's Blog

Related

How to use node package dotenv to access local development environment variables in Red Hat OpenShift application?

I'm revisiting a project which hasn't been updated for a while.
In production/online environment, it uses environment variables defined at:
openshift online console > applications > deployments > my node app > environment
In development/offline environment, it uses environment variables defined at:
./src/js/my_modules/local_settings (this file is ignored by .gitignore)
The code looks something like:
// check which environment we are in
if (process.env.MONGODB_USER) {
var online_status = "online";
}
else {
var online_status = "offline";
}
// if online, use environment variables defined in red hat openshift
if (online_status === 'online') {
var site_title = process.env.SITE_TITLE;
var site_description = process.env.SITE_DESCRIPTION;
//etc
}
// if offline, get settings from a local file
else if (online_status === 'offline') {
var local_settings = require('./src/js/my_modules/local_settings');
var site_title = local_settings.SITE_TITLE;
var site_description = local_settings.SITE_DESCRIPTION;
// etc
}
I would like to install the dotenv package in my local project repo via:
npm install dotenv
So that I can:
Have my local settings in a .env file in the root of my project (ignored in .gitignore)
Be able to use process.env.SOME_VARIABLE rather than local_settings.SOME_VARIABLE
Get rid of some if/else blocks as both scenarios would point to process.env.SOME_VARIABLE
I'm a bit confused as to how this would effect the online environment.
Seeing as both production/online and development/offline environments would use:
var some_variable = process.env.SOME_VARIABLE_HERE
would the application automatically know to:
Look at the local .env file when in development?
Look at the Red Hat environment variables when in production?
And would adding the required instantiation at the beginning of the server-side file:
require('dotenv').config()
somehow make Red Hat OpenShift freak out (as it seems to already have its own 'things' in place to resolve references to process.env.SOME_VARIABLE_HERE to the relevant values defined in the OpenShift console)?
To have a file by any environment (.dev .staging .prod) into the source code repository or manually in the server (it those are in .gitignore) worked for long time, but now it goes against to the devops.
The clean way is to use environment variables but managed remotely and obtained at the start of your application.
How it works?
Basically your apps don't read or need a file (.env .properties, etc) with variables anymore. It loads them from a remote http service.
Not intrusive
In this approach, you don't need specific languages variables (nodejs in your case). You just need to prepare your app to use environment variables. Your application don't care where the variables come from, just needs to be available at operative system level.
To achieve that, you just need to download the variables using a simple shell code or a very basic algorithm (http invocation) in your favorite language.
After that, after the start of your app, variables are ready to use at the most basic level.
var site_title = process.env.SITE_TITLE;
This approach is not intrusive because your app don't need something complex like library or algorithm in some programing language. Just needs the environment variables.
Intrusive
Same as previous alternative but instead to read the variables direct from environment system, you should use or create a class/module in your language. This offer your the variables you need:
var site_title = VariablesManager.getProperty("SITE_TITLE");
VariablesManager at the startup must have consumed the variables from a remote service (http) and the store them to offer them to whoever needs it through getProperty method.
Also this VariablesManager usually has a feature called hot-reload which at intervals, update the variables consuming the remote variables manager. With this, if your application is running in production with real users and some variable needs to be updated, you just need to change it in the variables manager. Automatically your app will load the new values, without restart or touching your app
This approach is intrusive because you need to load advanced libraries in some programing language or create it.
Devops
Your application just needs a few properties or settings related to the consume of remote variables. For example: variables of acme-web-staging:
remote_variables_manager = https://variables.com/api
application_id = acme-web-staging
secure_key = *****
You could hide the secure key and parametrize the application_id using environment variables (created in the platform console)
remote_variables_manager = https://variables.com/api
application_id = ${application_id}
secure_key = ${remote_variables_manager_key}
Or if you want one variable manager by each environment
staging
remote_variables_manager = https://variables-staging.com/api
application_id = acme-web
secure_key = *****
production
remote_variables_manager = https://variables-staging.com/api
application_id = acme-web
secure_key = *****
Variables manager
This concept was introduced many years ago. I used with java. It consist in a web application with features like:
secure login
create applications
create variables of an application
crypt sensitive values
publish http endpoints to download or query the variables by application
Here a list of some ready to use alternatives:
Configurator
Nodejs & mysql solution. I developed this and I use it in various projects.
Doppler
zookeeper
http://www.therore.net/java/2015/05/03/distributed-configuration-with-zookeeper-curator-and-spring-cloud-config.html
Spring Cloud
https://www.baeldung.com/spring-cloud-configuration
This is a java spring framework functionality in which you can create properties file with configurations and configure your applications to read them.
Consul
Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality.
doozerd, etcd
In your specific case
Don't use dot-env
Use pure process.env.foo
Deploy a remote variables manager in your openshift infraestructure
Create just one variable in your openshift web console: APP_ENVIRONMENT
In your code at the start, do something like this:
if (process.env.APP_ENVIRONMENT === "PROD")
//get variables from remote service using
//some http client like axios, request, etc
//then inject them to your process.env
process.env.site_url = remoteVariables.site_url
else
//we are in local developer workspace
//so, nothing complex is required
//developer should inject manually
//before the startup: npm run start or dev
//export site_url = "acme.com"
If you can configure an execution of a shell script before the start of your openshift app, you could load and expose the variables at that stage and the previous snippet would not be necessary because the variables will be ready to be retrieved using process.env directly in your app

How to run second node.js server from same folder with alternative configuration

I would like to run a second node.js server (using same code) running from the same directory as the first. I use the default.json file in the config folder for the 1st server and use the config library, ie
let config = require('config');
for the first server.
What is the recommended way to specify an alternative config file. Could you specify a custom config file to use from the command line? How would I do this in node.js?
config is able to read different config files based on a few environmental variables.
Since you'll be running multiple instances on the same system, you'll need to change NODE_APP_INSTANCE:
Create config files like this:
config/default.json: Default configuration shared across all instances.
config/default-1.json: Specific configuration for instance 1. May override values of default.json and/or add new ones.
config/default-2.json: Specific configuration for instance 2. May override values of default.json and/or add new ones.
Start your node processes with individual values for NODE_APP_INSTANCE:
Instance 1: NODE_APP_INSTANCE=1 node index.js
Instance 2: NODE_APP_INSTANCE=2 node index.js
Checkout the docs for more info.

Webpack bundle dynamic client config

We have a node.js app bundled for production using Webpack.
Our problem is how to add dynamic configuration after you already have a bundle, without the need to re-bundle?
On the server-side, we can just use node env variables, but how can this be done for the client bundle? Specifically, we need to tell a browser module to which api server address to connect.
Having a js/json file with the configurations causes the configuration values to be injected into the bundle, and therefore can't be changed afterwards (in a comfortable manner, without open the bundle file and manually finding and replacing).
Using something like express-expose, isn't something we want, since it causes another network request to get the data, and our server address is dynamic.
node-config etc., don't work on client side
You can make creative use of the externals option:
externals: [
{ appConfig: 'var appConfig' },
],
If you add that to your configuration you can just let your web server add a script tag with var appConfig = {"config":"value"}; somewhere before the loading of your webpack bundle, and a simple require('appConfig') will pick it up.

What is the laravel way of storing API keys?

Is there a specific file or directory that is recommended for storing API keys? I'd like to take my keys out of my codebase but I'm not sure where to put them.
This is an updated answer for newer versions of Laravel.
First, set the credentials in your .env file. Generally you'll want to prefix it with the name of the service, so in this example I'll use Google Maps.
GOOGLE_KEY=secret_api_key
Then, take a look in config/services.php - it's where we can map environment variables into the app configuration. You'll see some existing examples out of the box. You can add additional configuration under the service name and point it to the environment variable.
'google' => [
'key' => env('GOOGLE_KEY'),
],
Then when you need to access this key within your app you can get it through the app configuration instead.
// Through a facade
Config::get('services.google.key');
// Through a helper
config('services.google.key');
Be sure not to just use env('GOOGLE_KEY) through your app - it's more performant to go through the app configuration as it's cached - especially if you call php artisan config:cache as part of your deployment process.
You can make your API keys environment variables and then access them that way. Read more about protecting sensitive configuration from the docs.
You simply create a .env.php file in the root of your project that returns an array of environment variables.
<?php
return array(
'SECRET_API_KEY' => 'PUT YOUR API KEY HERE'
);
Then you can access it in your app like so.
getenv('SECRET_API_KEY');

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