Repository navigation
keyFilename makes 12-factor app style deployment difficult #136
Description
Activity
We should never assume that key file will be read from disk. We should require it to be passed as a plain object. Any other opinions?
I would add a
keyoption to pass the object, but keep the keyFilename is as well.
Some people like the 'download the key and pass the path to the constructor'™ approach, mostly in the getting started experience context.SGTM as we discussed offline.
Yes, both options is best.
keyFilename: 'path/goes/here.json'should more or less just be an alias forkey: require('path/goes/here.json')wherekeyaccepts a plain JavaScript object.keyFilename should work the way it works (without require), otherwise it becomes impossible to specify relative paths to keyFilename. See 7641028.
Interesting... I've never had issues with relative paths + require but I've never pushed it to its limits either. 😄
fs.readFileis definitely better anyway because it's async and won't automagically cache. 👍Just an end-user perspective/question, is the entire JSON really needed or is it just using the
private_keyvalue? If you were to add akeyoption I would potentially be confused if this is to the whole object or just the value specified for the keyprivate_keyin the downloaded JSON file.This confusion might be worsened in my example of using environmental variables as I would likely break the JSON file into four ENV variables like so:
declared environmental vars:
GOOGLE_CLOUD_private_key_id=value GOOGLE_CLOUD_private_key=value GOOGLE_CLOUD_client_email=value GOOGLE_CLOUD_client_id=value GOOGLE_CLOUD_type=valueInitializing gcloud-node:
var gcloud = require('gcloud'), bucket = new gcloud.storage.Bucket({ bucketName: YOUR_BUCKET_NAME, key: { "private_key_id": process.env.GOOGLE_CLOUD_private_key_id, "private_key": process.env.GOOGLE_CLOUD_private_key, "client_email": process.env.GOOGLE_CLOUD_client_email, "client_id": process.env.GOOGLE_CLOUD_client_id, "type": process.env.GOOGLE_CLOUD_type } });
We can rename the key to
credentialswhich is basically whatConnectionobject is doing at the moment. It's reading the file from keyFilename, parse and set it toConnection.prototype.credentials.Btw, you only need to provide
private_keyandclient_email.var gcloud = require('gcloud'), bucket = new gcloud.storage.Bucket({ bucketName: YOUR_BUCKET_NAME, credentials: { "private_key": process.env.GOOGLE_CLOUD_private_key, "client_email": process.env.GOOGLE_CLOUD_client_email, } });
@rakyll 👍 your example would address my original issue
- added 3 commits that reference this issue
on Aug 27, 2014 70 remaining items
- added a commit that references this issue
on Feb 3, 2026 - added a commit that references this issue
on Feb 25, 2026 - added a commit that references this issue
on Feb 26, 2026 - added a commit that references this issue
on Mar 5, 2026 - added a commit that references this issue
on Mar 18, 2026
I'm trying to use cloud storage which the documentation says I should initialize as such:
I dug into the code and this keyFilename option seems to be the only way to specify this required info, and it expects a filepath string. This makes storing the key's JSON as an environmental variable pretty complicated since I'd have to write the env value to a file, then pass the path to gcloud.
This seems to be a similar issue someone faced with Google APIs, a key file, and Heroku: http://ar.zu.my/how-to-store-private-key-files-in-heroku/
As he outlines, it seems there are four options, none super simple:
Even just having the option to pass this information in as a Javascript object (which makes sense for a node library) would be nice.