app.get('env') usage in localhost and production - javascript

var express = require('express');
var app = express();
var db_url;
if(app.get('env') == "development"){
db_url = 'mongodb://127.0.0.1:27017/localhost';
}else{
db_url = 'something else';
}
console.log(app.get('env'));
What does app.get('env') in express means? I'm seeing it still print development when I deploy my code to live server.

You need to tell it you're in production mode; see part of the Express docs.
In development, you typically set environment variables in your interactive shell, for example by using export or your .bash_profile file. But in general you shouldn’t do that on a production server; instead, use your OS’s init system (systemd or Upstart). The next section provides more details about using your init system in general, but setting NODE_ENV is so important for performance (and easy to do), that it’s highlighted here.
With Upstart, use the env keyword in your job file. For example:
# /etc/init/env.conf
env NODE_ENV=production
For more information, see the Upstart Intro, Cookbook and Best Practices.
With systemd, use the Environment directive in your unit file. For example:
# /etc/systemd/system/myservice.service
Environment=NODE_ENV=production
For more information, see Using Environment Variables In systemd Units.
If you are using StrongLoop Process Manager, you can also set the environment variable when you install StrongLoop PM as a service.
You can also set process.env.NODE_ENV in a JavaScript file if necessary.

Related

Dynamic settings in config.json from environment

In my config.json, I have a requirement for a setting object to be populated dynamically based on the environment variable setting.
"somesetting": {
"setting1": "%S1%",
"setting2": "%S2%"
}
My environment is Windows.
Many examples which I have come across have hard coded values and I am unable to understand how to handle my scenario. I am very new to npm and the javascript world. Any advice / references in this matter is really appreciated
Edit 2:
Possibly,I missed it, but my situation is that values of the %S1% and %S2% could be different in different environments. Consider S1 and S2 as some paths which are likely to be different based on which machine my code builds on the cloud e.g. C:\xyz or D:\xyz etc, which I would have no way of knowing upfront. So this means I can't have a static setting in it even if my environments are different.
Thanks
JSON is a static file and its content is a string, so you can't use variables here.
You can try to rewrite json file via javascript using fs module readFile and writeFile.
Maybe template engines like Handlebars and Mustache will help you to do that much easier.
But usually developers use one static file for one environment. You can change config only before starting your application, otherwise you can break it in a runtime (so bad for your users and customers).
Have a look at this
https://www.npmjs.com/package/config
It's JSON-based config.
We use this package for many years and it's quite good for a few environments.
Infrastructure
config/
- default.json
- development.json
- staging.json
- production.json
app.js
*/
Usage
/* default.json */
{
"HTTP": {
"PORT": 3001,
"MESSAGE": "Hello!"
}
}
/* development.json */
{
"HTTP": {
"PORT": 4001
}
}
/* app.js */
const config = require('config');
const message = config.get('HTTP.MESSAGE');
// "Hello!" (from default.json)
const port = config.get('HTTP.PORT');
// 4001 (from development.json, overrides 3001)
/* Windows */
set NODE_ENV=development& app.js
/* Linux */
NODE_ENV=development app.js
/* cross-platform */
cross-env NODE_ENV=development app.js
dotenv is a common solution for managing environment variables in node.js.
You can define an .env file for each environment you need. Then access them as node environment variables.
Depending on your use case, you could use environment variables to populate your config.json, or perhaps you won't need the config file at all and can just use the environment variables directly.
If I understand you correctly, you want to use Windows environment variables in your Node.js application so that the values are coming from the host operating system/environment itself rather than being hard-coded in a config file, which is a normal CICD requirement. Windows environment variables will be available wherever Node.js is installed by default. You don't need any additional packages. Both system and user environment variables will be available in Node.js process environment, process.env.whatever. For example:
const setting1 = process.env.setting1
const setting2 = process.env.setting2
However you cannot use them inside a .json file because they are static files, as #max-starling said. In this case I think a JavaScript config file makes more sense.
Main app.js
import config from './config'
console.log(config.setting1)
config.js
const somesetting = {
setting1: process.env.setting1,
setting2: process.env.setting2
}
module.exports = somesetting;
Node docs: https://nodejs.org/api/process.html#process_process_env

How to specify env variables in node app?

It's a lot of references to dotenv library to use when you want to specify env variables. But why? I can just specify my var in a file like this:
var dev = {
}
var prod = {
}
var config = null;
if (process.env.NODE_ENV === 'production') {
config = prod
} else {
config = dev
}
exports.config = config
and assign my var in npm srcipts, like this:
"scripts": {
"start": "NODE_ENV=dev node bin/dev",
"production": "NODE_ENV=production node bin/production"
}
Is my way not secure? Why is dotenv way recommended? Why should I create .env files instead my config.js?
Environment variables is the commonly assumed way to configure the behaviour of a program, across all programming languages. It is also supported out-of-the box in most CI/CD tools, as well working really well with the command line.
In your example, you assume that the complete config of the prd environment will be stored in the config, including db password etc. It is not considered secure to store any secrets in source code.
The.env file is a common utility for bundling environment variables. It is really is easy to create a .gitignore file with this pattern that prevents it from ever being committed so that configuration stays local. Note that the consumer of the package doesn't have to use a .env file but could also have global/local environment vars where the script is ran. Development solid and not so prone to mistakes.
Syntax simplicity. instead of creating an ad-hoc source code file containing configuration, with more complex syntax than key=value and less common to understand.
#Nastro, I'll point a little and simple different approach.
Develop your application 100% agnostic of an environment. In other words, keep away *from versioning files within your code or lots of if assigning different values to globals, sessions attributes and etc.
Favor your environments with the due env vars and values. Usually, the most strategic or special environments will be protected against unwanted access(production, staging and etc), so your secret values will be unreachable.
A single db_password = process.env.DB_PASS will be reusable for any existing and future environment you or your team creates.
This is a simple, yet effective approach, but demands a minimal control over your environment and hosts.

Setting default environment variables in Heroku

I'm working on an app that connects to third-party APIs which require the use of an APP ID and SECRET KEY.
I am storing these values as environment variables in heroku, so that I don't need to expose them in my code.
If I deploy to heroku, it will use heroku's environment variables to resolve these API credentials.
If I'm working on it locally, I want to use my config.js module, and lookup the API credentials there. NOTE: This config.js file is included in my .gitignore so that these credentials never end up in the cloud.
The problematic code is this:
var api_secret = process.env.API_SECRET || require('../../config.js').secret;
When I run this locally, I've got no issues. Meaning, it is unable to resolve the environment variable, so instead it uses the secret from within config.js.
When I run it on heroku, it DOES throw an error telling me that module 'config.js' could not be found. This makes sense, because it was never pushed up with the rest of the repo, by virtue that it is in my .gitignore.
Because heroku is parsing through my code before it ever runs, the require('../../config.js') is problematic. It is trying to lookup a file that doesn't exist.
How can I solve the issue of using environment variables when deployed, and the config.js module when running locally?
On the Heroku dashboard for your application, you can set config variables. If you have the Heroku Toolbelt set up on your machine, you can also use:
heroku config:set API_SECRET=secret
See this article for more.
Edit: Think I may have misunderstood the question. I would suggest, if possible, using the dotenv npm package to set your config variables locally.
If not, another thing to check would be that the config.js package is in your package.json file, because Heroku will use this to build your dependencies.
If you do not want to push your config.js to heroky at all, you can just follow the following to determine whether the config file exists or not with a try catch and the file system module:
Check synchronously if file/directory exists in Node.js
In your case:
var fs = require('fs'),
api_secret,
config;
try {
// Check whether config.js exists
config = fs.lstatSync('../../config.js');
// If we reach this line then config.js exists, yay!
api_secret = process.env.API_SECRET || require('../../config.js').secret;
// or alternatively api_secret = require('../../config.js').secret;
// depending on your logic
}
catch (e) {
// else config.js does not exist
api_secret = process.env.API_SECRET
}
To run Heroku commands programmatically, you can set up a free Ruby app and make it do what you want through API calls. Use Heroku-api. See https://github.com/heroku/heroku.rb
If you want to set Heroku commands manually, you can set env variables on Heroku either with the command heroku config:set MYVAR=MYVALUE or through the Heroku dashboard (Click on your app > settings > reveal config vars > edit).

Sails.js, application file not generated

I'm new to Sails.js and are now working through some tutorials.
I have now created my Sails application and added a User model and controller. The application runs when executing sails lift. I am able the view the users and create more.
I cannot find the below referenced file that is supposed to contain basic application settings such as application name, port, environment and log level.
config/application.js
Am I missing something or did I create the application wrong?
port and loglevel should be set in config/env/[production|development]
I think the name of the application is taken from the package.json if I'm not mistaken.
Sails have improved this setup. Now you should have an env folder under config with an environment config file. For example development.js
module.exports = {
port: 1337
};
This will set the port for that environment. This environment is either set as the environment variable 'NODE_ENV' or you can specify this in your local.js file. Like so.
environment: development'
Note any variables set here can be accessed by using
sails.config.variable
So you can set up your own appname variable and access it like that.

Node.js: How to setup different variables for prod and staging

I'm using Express and I need to use different credentials for each server (staging and production).
I could setup the variables in the server.coffee file but then I'd need to access those variables in different files.
server.coffee:
app.configure 'production', () ->
app.use express.errorHandler()
What's the solution? Setup the variables and then export them?
./config.js
var development = {
appAddress : '127.0.0.1:3000',
socketPort : 4000,
socketHost : '127.0.0.1',
env : global.process.env.NODE_ENV || 'development'
};
var production = {
appAddress : 'someDomain.com',
socketPort : 4000,
socketHost : '8.8.8.8',
env : global.process.env.NODE_ENV || 'production'
};
exports.Config = global.process.env.NODE_ENV === 'production' ? production : development;
./app.js
var cfg = require('./config').Config;
if (cfg.something) { // switch on environment
// your logic
}
This might be a good place to use npm-config.
When running scripts (see npm-scripts(7)) the package.json "config" keys are overwritten in the environment if there is a config param of <name>[#<version>]:<key>
I would not use them for every type of variable configuration setting, but I think it's a good solution for simple cases like URLs and ports because:
You put them directly into package.json.
In addition, you can specify them on the command line or as ENV variables.
Anything run through npm can refer to them (e.g., scripts).
You can set them per-user with `npm config set foo:port 80
The one caveat is that the config parameter in your package.json is only automatically exported into the environment when you run your code through npm. So, if you just run it with node, like, node ./myapp.js, then you can't expect that process.env.npm_package_config_foo will contain your value. However, you can always var pkg = require('./package.json'); and access the values at pkg.config.
Because it might not be immediately obvious, I'd also add that the npm_package_config environment variables do not bubble up to apps that depend on your npm package. So, if your depended-on package refers to process.env.npm_package_config_foo, then the dependent package would have to define that in its own package.json. I guess since it's an "npm_package_config" it wouldn't make sense to push them all the way up the tree.
So, how would I use one npm config variable and have it work all the way up the tree, in both the base package and the packages that depend on it? It's actually a little confusing, and I had to figure this out through trial and error.
Let's say you have a package connector and package client. client depends on connector and you want to specify a config parameter for connector that can be used or overwritten in client. If you use process.env.npm_package_config.port in your connector module, then when it's depended on in client module, then that variable won't be exported and it will end up as undefined.
However, if you instead use process.env.npm_config_connector_port (notice the first one starts with npm_package_config and the other with npm_config_packagename), then you can at least set that in your .npmrc using npm config set connector:port 80 and it will be "namespaced" as process.env.npm__config_connector_port everywhere that you run npm, including scripts that you run in client that depend on connector, and you'll always be able to overwrite it on the command line, in your ENV, or in your .npmrc. You just have to keep in mind that, as with any environment variable, it may not always be set. So, I would use the default operator with the process.env.npm_config_connector_port as the first (preferred) value:
var port = process.env.npm_config_connector_port || sane_default
Here, sane_default could be populated from one of the other recommended methods. Personally, I like keeping configuration data like these in JSON files at the very least, and package.json seems like the best JSON file to put them in. Store them in data instead of code and then you can easily use the static JSON in-line, generate them dynamically, or pull them from the filesystem, URLs or databases.
I have uploaded an implementation into https://github.com/qiangyu/nodejsconfig. I believe it will satisfy your needs. Basically, you only need to provide one configuration file:
dev.appAddress = '127.0.0.1:3000';
prod.appAddress = 'someDomain.com';
Then, you use following code to read the appAddress in prod environments:
var xnconfig = require('nodejsconfig');
var fs = require('fs');
var data = fs.readFileSync(__dirname+"/config.properties", "UTF8");
// assume we will be using environment "prod"
var config = xnconfig.parse("prod", data);
// the output will be someDomain.com
console.log(config.getConfig("appAddress"));
If you don't want the logic for determining which config to use in each file (which would look pretty ugly), you'll have to export it somewhere.
What I would suggest: Have a config.json file containing the different configs. The main file requires it and does something like config.default = config.(condition ? 'production':'development'). In all other files, you can now just do require('./config').default.
I have an app which uses three different methods of declaring config variables (uris, api keys, credentials, etc.) depending upon the environment (production = environment variables; staging = command line args; local = config files.)
I wrote a little "config" module to handle merging all of these options into one object that I can use in my app and uploaded it as a gist: https://gist.github.com/1616583
It might not be the best implementation, but it's been working pretty well so far :).

Categories

Resources