How to deal with environment variables, source control & serverless.yml

Here’s a common situation:

  1. I have environment variable secrets I’d like to use
  2. I have a serverless.yml file
  3. I’d like to commit serverless.yml to version control

How do I manage all these desires without committing secrets to git? Is there a better way than just never committing serverless.yml?

Just focusing on the AWS ecosystem:
Is there upcoming functionality to use encrypted environment variables in serverless.yml and have kms decrypt them?

Opened up a more detailed github question here - https://github.com/serverless/serverless/issues/472

I store my environment variables in the root of my project in a .env file that’s in the .gitignore and I’ll load that into a JS file that can be referenced via serverless.yml

Ex:

/
  .env
  serverless.yml
  /config
    envVars.js

serverless.yml

provider:
  environment:
    VALUE1: ${file(./config/envVars.js):getEnvVars.value1}
    VALUE2: ${file(./config/envVars.js):getEnvVars.value2}

.env

VALUE1=foo
VALUE2=bar

/config/envVars.js

const dotenv = require('dotenv');

// require and configure dotenv, will load vars in .env in PROCESS.ENV
dotenv.config();

module.exports.getEnvVars = () => ({
  value1: process.env.VALUE1,
  value2: process.env.VALUE2
});

This will allow you to pull your environment variables from a local .env file or straight from the environment (like in CI).

4 Likes

Check the serverless-kms-secrets plugin (https://github.com/SC5/serverless-kms-secrets). It allows you to encrypt variables using KMS.
The module is still at its early phases, some rough edges in the dev experience that need to get polished but gets the job done.

The long version - Read this http://www.goingserverless.com/blog/keeping-secrets-out-of-git

The short version -

Create a secrets.yml that looks something like

default: &default
  <<: *default
  COMMON_API_KEY: "AN API KEY COMMON TO ALL ENVIRONMENTS"
  COMMON_API_SECRET: "AN API KEY COMMON TO ALL ENVIRONMENTS"

dev:
  <<: *default
  API_KEY: "YOUR DEVELOPMENT API KEY"
  API_SECRET: "YOUR DEVELOPMENT API SECRET"

stage:
  <<: *default
  API_KEY: "YOUR STAGING API KEY"
  API_SECRET: "YOUR STAGING API SECRET"

prod:
  <<: *default
  API_KEY: "YOUR PRODUCTION API KEY"
  API_SECRET: "YOUR PRODUCTION API SECRET"

Add secrets.yml to your .gitignore

Put this into your serverless.yml

custom:
  stage: ${opt:stage, self:provider.stage}
  secrets: ${file(secrets.yml):${self:custom.stage}}

Then reference the secrets like ${self:custom.secrets.API_KEY} etc…

1 Like

This might be completely irrelevant, but I found it useful.

If you are using gitlab, you can run your deployments from gitlab-ci and it will store your secrets separately from the repo in the project settings. You can easily configure it to deploy automatically, for example, whenever a tag is added.

This article talks about it: https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/