Rails Custom Environment Credentials Migration

Introduction

Rails 5.2 introduced a new credentials API where one could store key/value pairs in an encrypted file - which can and should be checked in your git repository - managed by rails and rails would generate a key file - which shouldn’t be checked in - in order to decrypt the first file.

The credentials are managed using:

bin/rails credentials:edit

which would generate by default:

  • config/credentials.yml: the encrypted file
  • config/master.key: key to decrypt the file

Since at this time there was no enviroment (i.e.: staging, production, … etc) specific API, one would usually build some structure in the key/value pairs to represent enviroment specific credentials, for example:

production:
  aws:
    key: 123
staging:
  aws:
    key: 345

Then use Rails.credentials[Rails.env].aws.key

Rails 6 added support for multi environment credentials where one can specify the environment when editing the credentials file, for example

bin/rails credentials:edit --environment staging

which would create a config/credentials/staging.yml and config/credentials/staging.key, this applies for other environments too.

Good news is the support for multi environment credentials is backward compatible, it wasn’t really clear to me what that actually means, but after some investigation I could put it in some simple words:

If Rails couldn’t find a matching credentials file/key for the current environment, it will fallback to config/credentials.yml and config/master.key

How to migrate to multi environment rails credentials?

Now coming to the main part of this post, how can one migrate to the new multi environment credentials?

Method A

If you have the luxury and time to change the deployment pipeline and server setup to move away from config/credentials.yml and config/master.key in favor of new config/credentials/production.yml and config/credentials/production.key then go for it. You will need to move from the custom environment structure that you might have had in credentials.yml to a flat structure in the respective environment credential file. For example:

This credentials.yml file would be splitted into:

production:
  aws:
    key: 123
staging:
  aws:
    key: 345
  1. A production config/credentials/production.yml
aws:
  key: 123
  1. And staging config/credentials/staging.yml
aws:
  key: 345

Then in your code to access this key you’ll just use Rails.credentials.aws.key.

Method B

If changing deployment/server setup is not an option then you can keep the generic credentials file for production environment and create new credentials for other environments. For example:

This credentials.yml file would change to:

production:
  aws:
    key: 123
staging:
  aws:
    key: 345
  1. A changed credentials.yml
aws:
  key: 123
  1. And a new staging.yml
aws:
  key: 456

Then the key can be accessed in the same way as Method A: Rails.credentials.aws.key.

I hope this was helpful for you and maybe inspired you to migrate your credentials, if you have any suggestions on how to improve this post or had already a similar experience and would like to share it please drop me a comment or an email.

Note: All yaml/key file names mentioned in this post assume the default Rails configuration for credentials.

comments

comments powered by Disqus