Best practices for managing multiple environment variables in prodution

2.6k views Asked by At

Although I am not familiar with DevOps best practices, I am trying to come up with a reliable and efficient method for managing multiple variables in production. The following represents my current approach:

/
|ENV_VAR.sh
|--/api1
|--/staging.api1
|--/api2
|--/staging.api2

Where:

ENV_VAR.sh

### API 1 variables ###
export API1_VAR_1=foo
export API1_VAR_2=foo2
export API1_STAG_VAR_1=foo_stag
export API1_VAR_2=foo2_stag2

### API 2 variables ###
export API2_VAR_1=foo
export API2_VAR_2=foo2
export API2_STAG_VAR_1=foo_stag
export API2_VAR_2=foo2_stag2

The API 1 and 2 are two nodejs-based apps running in the same server using a reverse-proxy configuration. If nothing goes bad with the server (e.g. unexpected shutdown), I just have to (re)set the variables once in a while via SOURCE ENV_VAR.SH in order to make sure that new variables are defined.

Before proceeding with this approach, I would like to know whether it is correct at all, or if it has a big flaw. If this approach is alright, how to automatically (re)source the environment variables from the package.json whenever a new version of any App is deployed? (just to guarantee that the variables are still defined)

Thanks in advance.

1

There are 1 answers

2
O. Jones On

I like using Loren West's config package for these configuration parameters. I happen to like to extend it with the properties package: that way I don't have to put parameters in valid, comment-free, JSON format. JSON5 also helps solve the readability problem, but I haven't tried it.

Why do I like this?

  1. It gives a structured way of dealing with development / test / staging / production environments. It keys off the ENV environment variable, which of course has values like development and production.

  2. All properties files go into a single directory, typically ./config. Your production krewe can tell what they're looking at. default.properties, development.properties and production.properties are the names of typical files.

  3. Most configuration parameters don't have to be secret, and therefore they can be committed to your repository.

  4. Secrets (passwords, connection strings, API keys, etc) can be stored in local.properties files placed into ./config by your deployment system. (Mention local.properties in your .gitignore file.)

  5. Secrets can also be loaded from environment variables, named in a file called ./config/custom_environment_variables.json.

  6. It works nicely with pm2.

This is really easy to configure.

Your files:

 default.properties   (used when not overridden by another file)
 [API1]
 VAR_1 = foo
 VAR_2 = foo2
 [API2]
 VAR_1 = foo
 VAR_2 = foo_for_api2

 staging.properties
 [API1]
 VAR_1 = foo_stag
 VAR_2 = foo2_stag2
 [API2]
 VAR_1=foo_stag
 VAR_2=foo2_stag2

 custom_environment_variables.json
 {
   "API1" : {
     "password": "API1_PASS"
   },
   "API2" : {
     "password": "API2_PASS"
   }
}

Your nodejs program:

const config = require( 'config' )
require( 'properties' )
const appConfig = config.get( 'API1' )

const var1 = appConfig.VAR_1
const password = appConfig.password

Then you run your program with API1_PASS=yaddablah nodejs program.js and you get all your configs.