Simple & Secure Config Management for Node.js

Github Repo →

Define all your config in one place.

Define all your config in one place.

Strong Config will load the correct config file based on your NODE_ENV

Strong Config will load the correct config file based on your NODE_ENV

Have you ever...


❓...struggled with config drift between local, staging, prod...?

❓...forgot to update the production config after updating the development config?

❓...forgot to tell your teammates to update their local .env files after you made a change?

❓...worried about leaking secrets by accidentally pushing your .env files to GitHub?

❓...wished you could nest config values in your .env just like in a JavaScript object?

❓...had a CI build fail due to environment variable issues?

💪 Strong Config is here to help!


Example Config


You can define config files as JSON or YAML

Config before encryption

Here is a raw config as you would create it during development:

# A top-level config value which will be available to your application
# as `config.logger`
**logger**:
  # A nested value which will be available as `config.logger.level`
  level: DEBUG

**auth**:
  apiClientId: non-secret-client-id
  # A secret value. Every key with a 'Secret' suffix will be
  # encrypted by Strong Config (e.g. 'encryptMeSecret')
  apiSecret: top-secret-api-credential

# A dynamic value that will be substituted at runtime with the respective
# value of the environment variable $SHELL 
shell: ${SHELL}

Config after encryption

Here is how an encrypted config file looks like after running strong-config encrypt

**logger**:
  # This value remains as is because it doesn't have a 'Secret' suffix
  level: DEBUG

**auth**:
  apiClientId: non-secret-client-id
  # This is now encrypted and safe to commit into version control :)
  apiSecret: ENC[AES256_GCM,data:aeQ+hlVIah7WyJoVR/Jbkb6GLH7ihsV0D81+U++pkiWD0zeoRL/Oe9Q3Tz6j/TNvKKVDnohIMyw3UVjELOuSY+A==,iv:nVRZWogV4B7o=,tag:KrE2jssfP4uCvqq+pc/JyQ==,type:str]

# Also still the same value which will be substituted only at runtime
shell: ${SHELL}

# The below section is auto-generated by [sops](<https://github.com/mozilla/sops>) and contains important metadata to
# decrypt the config at runtime. **Do not manually edit or delete this section.**
**sops**:
  gcp_kms:
    - resource_id: projects/my-project/locations/europe-west1/keyRings/my-project-key-ring/cryptoKeys/my-strong-config-key
      created_at: '2020-01-07T10:11:12Z'
      enc: AiAAmdAgj1dw1XdD2MsVpvmA4Deo867hmcX2B3NDhe9BCF2axuZ18hJJFK9oBlE1BrD70djwqi+L8T+NRNVnGUP+1//w8cJATAfJ8W/cQZFcdFTqjezC+VYv9xYI8i1bRna4xfFo/INIJtFDR38ZH1nrQg==
  lastmodified: '2020-01-07T10:11:12Z'
  mac: ENC[AES256_GCM,data:ABcd1EF2gh3IJKl4MNOpQr5stuvWXYz6sBCDEfGhIjK=,iv:A1AaAAAaa111a1Aa111AA/aaaAaaAAaa+aAaAaAAAaA=,tag:AAaaA1a1aaaAa/aa11AaaA==,type:str]
  encrypted_suffix: Secret
  version: 3.5.0

Getting Started


  1. Create a new Node.js app

    mkdir -p strong-config-test/src
    cd strong-config-test
    git init
    yarn init --yes
    touch src/config.js
    
  2. Install Strong Config

    yarn add @strong-config/node
    

    <aside> 💡 Sidenote: The Sops Binary After package installation, Strong Config automatically runs a postinstall script that checks for availability of the sops binary on your system. If it can't find the sops binary, it will try to download it to node_modules/.bin/sops which is always part of $PATH when you run yarn run or npm run scripts. Alternatively, you can also install sops globally via brew install sops (macOS). For other systems check the official sops releases on GitHub.

    </aside>

  3. Create a config file

    # By default, strong-config uses the ./config folder.
    # You can configure this to be a different folder via the [options](<https://www.notion.so/brickblock/Strong-Config-e5dc221a7da34ef5a020707618f2f2dc#311640a59e5d45b49eccf6e3d66e11e1>)
    mkdir config
    
    # We'll use YAML here, but JSON is also supported
    echo "myFirstConfig: strong" > config/development.yml
    echo "myFirstSecret: a development secret" >> config/development.yml
    
  4. Load config in your application code

    /* src/config.js, or anywhere else you want to use config values */
    
    const StrongConfig = require('@strong-config/node')
    
    // Instantiate StrongConfig, then decrypt and load config file
    const config = new StrongConfig().getConfig()
    
    // This will print "{ myFirstConfig: 'strong' }" to the console
    console.log(config)
    
    /* 
     * OPTIONAL (but recommended)
     * Call `new StrongConfig()` just once in your application, then
     * export the memoized config object for other files to import.
     * 
     * If you call `new StrongConfig()` again from another file, it would
     * work, but would read the config from disk again which is slower than
     * loading it from memory.
     */
    module.exports = config
    
  5. Add yarn start script to your package.json

    {
      ...
    
      "scripts": {
        "start": "node src/config.js"
      }
    
      ...
    }
    

    <aside> 🚨 Warning: If you try running node src/config.js directly from your terminal, it will fail if you haven't installed sops globally. Wrapping it in a yarn/npm script is safer because all yarn/npm scripts automatically load ./node_modules/.bin in the $PATH, where a local version of Sops has been downloaded to by the postinstall hook.

    </aside>

  6. Run your app

    Strong Config determines which config file to load based on the NODE_ENV environment variable. If you'd like to use a different env var, this is configurable via the options.

    # Start app in 'development' mode which loads ./config/**development**.yml
    NODE_ENV=**development** yarn start
    

    <aside> 🚨 Warning: If you omit setting NODE_ENV=your-env then Strong Config will fail because it doesn't know which config file it's supposed to load.

    </aside>

Going Live


  1. Add a production config

    touch config/production.yml
    

    with the following content:

    myFirstConfig: strong in production
    myFirstSecret: super-duper-production-secret
    
  2. Add a pre-commit git hook to avoid checking in unencrypted secrets Add Husky via yarn add --dev husky, then add the following to your package.json:

    "husky": {
      "hooks": {
        "pre-commit": "strong-config check"
      }
    },
    

    Now try committing a config file with a secret and see that Strong Config protects you:

    https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6b8bda6c-5841-48d3-9625-95e5c076b504/Carbonize_2020-07-10_at_14.51.35.png

  3. Set up Encryption Provider Hook up your encryption key provider of choice. Check this deep dive on how to set up an encryption provider: Encryption

Powered by Fruition