Rails Credentials can be Confusing
Jon Sully
2 Minutes
Some conventions to follow
Rails’ encrypted credentials feature is neat but can be a bit confusing and docs are quite minimal. For my own future’s sake, here are a brief set of explanations and conventions to follow.
For backwards compatibility reasons and history, your app may have a ‘global’ credentials file. This consists of the file pair:
~/config/credentials.yml.enc ~/config/master.key
Additionally, Rails 6 brought environment-specific credentials files consisting of credential file-pairs in ~/config/credentials/
such as:
~/config/credentials/development.yml.enc ~/config/credentials/development.key ~/config/credentials/production.yml.enc ~/config/credentials/production.yml.enc
If the environment-specific yml files exist they will take precedence over the ‘global’ file. So even if you’re just doing local development, the presence of development.yml.enc
will cause Rails to load that file, not the global credentials.yml.enc
.
You may edit your environment-specific credentials files by passing -e=<ENV>
to rails credentials:edit
and only by passing that flag (or its more verbose variant). Setting the RAILS_ENV does not control credentials:edit like basically all other rails tasks. E.g.
RAILS_ENV=production rails credentials:edit
Will not edit the production credentials file. Strange right? Basically every other Rails command follows RAILS_ENV
, but not this one. Beware, this can catch you really off guard. You need to pass the environment you want to edit as a specific argument to the task:
rails credentials:edit -e production # or rails credentials:edit --environment production
There’s a bit of an ongoing discussion as to why this is the case, but as George Claghorn summarized, one shouldn’t have to boot the Rails app in Production mode (which may not be possible to do locally) just to edit the production credentials. It makes sense, but having a Rails task that doesn’t adhere to RAILS_ENV
leaves a bit of a tension 🤔
Beyond that, having a mix of the ‘global’ credentials file and some environment-specific credentials files can also be a bit of a foot-gun. Forgetting which is which, when/where each is loaded, and that we need to add credentials to more than one file can make for a not-fun-day. I’d recommend either using the global credentials configuration (single pair of files, all environments share the same keys) or environment-specific credentials files with no global file so that each environment gets their own keys without having to worry about which credentials file gets loaded into the app.
Finally, environments that aren’t suitable for transfering a *.key
file to (staging, prod, remote environemnts) need to use the environment variable RAILS_MASTER_KEY
, which, despite using the name ‘master key’ should actually just contain the decryption key for that environment (the same string of characters contained within that environment’s *.key
file).
Comments? Thoughts?
Anonymous
Also each environment master key (i.e. development.key, production.key, etc.) must never be checked into source control and are usually loaded as an environment variable in the shell which makes editing credentials for different environments a cumbersome process of reexporting RAILS_MASTER_KEY. It’s not elegant.
February 2023
Will not edit the production credentials file. Strange right? Basically every other Rails command follows RAILS_ENV, but not this one. Beware, this can catch you really off guard. You need to pass the environment you want to edit as a specific argument to the task:
Jon Sully (Author)
For now, anyway! Turns out this is changing in Rails 7.1! This was just merged: https://github.com/rails/rails/pull/47107
April 2023 Calendar
If the environment-specific yml files exist they will take precedence over the ‘global’ file. So even if you’re just doing local development, the presence of development.yml.enc will cause Rails to load that file, not the global credentials.yml.enc.
Betina Jessen
Handling sensitive data, such as API keys or database credentials, is a critical aspect of application security. The credentials feature in Rails provides a convenient and secure way to store and access this sensitive information. However, due to its intricacies, it can sometimes be a source of confusion for developers. This comment recognizes the potential difficulties developers may face when working with Rails credentials, such as understanding the encryption process, managing multiple environments, or integrating with deployment systems. It underscores the importance of thorough documentation, best practices, and proper education on effectively utilizing Rails credentials to ensure the security and confidentiality of sensitive data. By addressing the confusion surrounding Rails credentials, developers can enhance their understanding and utilization of this essential feature, thus strengthening the overall security posture of their Rails applications. Printable calendar 2023
monthlycalendar2023
Beyond that, having a mix of the ‘global’ credentials file and some environment-specific credentials files can also be a bit of a foot-gun. Forgetting which is which, when/where each is loaded, and that we need to add credentials to more than one file can make for a not-fun-day. I’d recommend either using the global credentials configuration (single pair of files, all environments share the same keys) or environment-specific credentials files with no global file so that each environment gets their own keys without having to worry about which credentials file gets loaded into the app. August 2023