DEV Community

Cover image for How to Create Configurations for Different Environments in Your Node Applications

How to Create Configurations for Different Environments in Your Node Applications

Having multiple configurations can be handy for your node applications. It is quite probable that your applications will run in different environments and require slightly different configurations between them. For example, when you are developing, you may be using your local mysql for your database connection; this will not be the case in a production or stage environment.

This article will show you how to set up different configurations, for different environments, across your applications.

Contents

  1. Basic setup
  2. Creating your npm scripts
  3. Configurations
  4. Implementation
  5. Conclusion

Basic setup

What you need to do:

  1. Create your package.json file using npm init.
  2. Save the config dependency in your application.
  3. Create your index.js file, which will be your entry point specified in step 1.
  4. Create your configuration files inside a config directory.
npm init    # accept defaults
npm install –save config
touch index.js

# create configuration dir and files
mkdir config
touch config/default.json
touch config/production.json
Enter fullscreen mode Exit fullscreen mode

Npm scripts

Now, create 2 scripts, which:

  1. set your NODE_ENV to test and runs your application
  2. set your NODE_ENV to production and runs your application

The NODE_ENV should be set to the same name as one of your configuration files. If it is not, then the default configuration will be used.

In this example, you set your NODE_ENV to test and production. As test does not have its own configuration file, the default will be used. Production does have its own configuration file, therefore your production configuration will be used, when running production script.

Linux

β€œscripts”: {
  β€œtest”: β€œexport NODE_ENV=test && node index.js”
  β€œproduction”: β€œexport NODE_ENV=production && node index.js”
}
Enter fullscreen mode Exit fullscreen mode

Windows
Notice the lack of a space before the ampersands.

β€œscripts”: {
  β€œtest”: β€œset NODE_ENV=test&& node index.js”
  β€œproduction”: β€œset NODE_ENV=production&& node index.js”
}
Enter fullscreen mode Exit fullscreen mode

Configurations

Now, add your configurations:

  1. Default configurations
  2. Configurations to be used in production

The default configurations will be used across all environments. When a property cannot be found in its specific configuration mode, then it will check to see if it exists in the default configuration before throwing an error.

config/default.json

{
  β€œdatabase”: {
    β€œhost”: β€œlocalhost”,
    β€œport”: 3306,
    β€œusername”: β€œroot”,
    β€œpassword”: β€œPassw0rd!”,
    β€œdbName”: β€œapp”
  }
}
Enter fullscreen mode Exit fullscreen mode

config/production.json

{
  β€œdatabase”: {
    β€œhost”: β€œ192.168.1.1”,
    β€œusername”: β€œroot”,
    β€œpassword”: β€œsomethi1ngAbitM0r3Secur3”,
    β€œdbName”: β€œapp”
  }
}
Enter fullscreen mode Exit fullscreen mode

Notice how the port property is not set in the production configuration.

If you are running in production, and you try to access the port property, it will retrieve the port value from your default configuration, as it is not specified in the production.json.

Use the default configurations for common properties that occur between all your environments.


Implementation

In order to access your configurations, you need to do 3 things:

  1. Require in the config dependency.
  2. Check the existence of your configuration property using the has method.
  3. Get the value of your configuration property using the get method.

If a configuration property is not found, and you try to access it, an error will be thrown. Therefore, it is good practice to check the existence of a property using the has method, as seen in the example below.

Index.js

const config = require(β€˜config’);

// the NODE_ENV you set in your package.json scripts
console.log(process.env.NODE_ENV);

// Does the property exists? If so assign the values to variables, else assign null
const host = config.has(β€˜database.host’) ? config.get(β€˜database.host’) : null;
const port = config.has(β€˜database.port’) ? config.get(β€˜database.port’) : null;

if (!host || !port) {
  console.error(β€˜database configuration settings not set’);
}

console.log(`${host}:${port}`);
Enter fullscreen mode Exit fullscreen mode

Conclusion

If you are running your applications in multiple environments, consider using this approach, especially if you have a lot of configurations to be set, e.g. database connections, email settings, remote logging configurations, etc.

Be aware that you do not add any sensitive information to your source control if you are using public repositories for your applications.


Header photo by Adi Goldstein on Unsplash

Discussion (6)

Collapse
ajustee profile image
Ajustee

Another option to support multiple environments is move settings into cloud. Ajustee is cloud software configuration management solution that offers:

  • api to retrieve single configuration key, subset of keys or entire configuration set;
  • set up default values for entire product, plus different values for environments;
  • override config values for a subset of users based on myriad of application parameters, including percentage redirect & schedule;
  • build setting forms with rich data validation rules to ensure there are no typos or other human errors that easy to make and difficult to troubleshoot;
  • automated audit log to review who has accessed the system or what operations have been performed;
  • automatic scheduled backups to restore to previous configuration sets at any time;
  • retrieve slack notifications every time there is a change in configuration values;
  • Secure access to settings based on IP addresses and configuration namespaces;
  • Secure access to web console with two-factor authentication and IP address restrictions;

Service offers free 30 day trial. DM me if you need more time to evaluate the product.

Collapse
dgreene profile image
Dan Greene

don't ever code db parameters (INCLUDING PASSWORD) in a file that's in source control.... -1 point.

Collapse
jrdev_ profile image
Jr. Dev πŸ‘¨πŸΎβ€πŸ’» Author

I'm guessing you missed the bold text at the bottom.

Dont ever comment on an article critiquing it without first reading the full contents... -1 point

Collapse
dgreene profile image
Dan Greene

Fair enough, but why even use that as an example, if you immediately say "don't do this"? You could have picked API url endpoints, or other non-secure environment specific configuration values to use as an example.

That said, I fully concede my skimming the last paragraph, and accept my -1.

Thread Thread
jrdev_ profile image
Jr. Dev πŸ‘¨πŸΎβ€πŸ’» Author

πŸ˜‚ you gracefully accepted that -1, well played πŸ‘

I'm not saying not to do it, the configurations in the example could be fully legit, I'm just saying don't add it to source control.

Collapse
zilti profile image
Daniel Ziltener

Another suggestion: 12factor.net/ :-)