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 fileconfig/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
andconfig/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
- A production
config/credentials/production.yml
aws:
key: 123
- 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
- A changed
credentials.yml
aws:
key: 123
- 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.