How to use Environment Variables in GCloud App Engine (Node.js)

2017-04-10

Don’t put your secret information in your code

App Engine allows one to define environment variables through app.yaml. But you probably want to commit app.yaml to your version control (e.g. git).

How to solve this dilemma?

Store secrets in Google Cloud Storage

Go to Google Cloud -> Storage -> Browser.

Create a Bucket. The name should include:

  • “envvars”
  • your project name
  • your domain (optional)

Let’s say I create a project named “blog”, to host my blog. I would name it envvars.blog.gunargessner.com.

Bucket names are unique across Google Cloud (not just Company or Project wide). Names ending with a domain are reserved. But you have to go through the trouble of verifying ownership.

Upload to this bucket your .env file. Example:

.env
1
2
MY_API_KEY=xxxx-xxxx-xxxx-xxxx
MY_OTHER_API_KEY=xxxx-xxxx-xxxx

Importing Bucket content into process.env

Install dependencies

1
npm install --save @google-cloud/storage dotenv

Add prestart hook to package.json

package.json
1
2
3
4
"scripts": {
"prestart": "node getEnv",
"start": "node index.js"
}

Add script to download .env

getEnv.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'use strict'
const fs = require('fs')
const dotEnvExists = fs.existsSync('.env')
if (dotEnvExists) {
console.log('getEnv.js: .env exists, probably running on development environment')
process.exit()
}
// On Google Cloud Platform authentication is handled for us
const gcs = require('@google-cloud/storage')()
const bucketName = `envvars.${process.env.GCLOUD_PROJECT}.gunargessner.com`
console.log(`Downloading .env from bucket "${bucketName}"`)
gcs
.bucket(bucketName)
.file('.env')
.download({ destination: '.env' })
.then(() => {
console.info('getEnv.js: .env downloaded successfully')
})
.catch(e => {
console.error(`getEnv.js: There was an error: ${JSON.stringify(e, undefined, 2)}`)
})

Use dotenv to load content into process.env

index.js
1
2
3
4
5
'use strict'
require('dotenv').config() // Loads .env
// ...

Making it work locally (development environment)

It works out of the box if you have a .env file in your local environment.


Changelog

1
2
3
2017-05-02 Switched to Storage instead of Datastore
Previous implementation used Google Cloud Datastore.
There's too much friction in using a database for storing environment variables.

Comments: