What this feature is for
The credentials feature is a way of storing secrets that you don’t want to keep in plaintext, like AWS credentials for example. (In fact, the one and only thing I keep in my main Rails project’s credentials are my Active Storage AWS credentials.)
Why the credentials feature is difficult to learn about
I personally have found Rails credentials really hard to understand. I think there are three reasons why this is.
- The official Rails docs about the credentials feature are a little terse and not easily discoverable.
- The feature changed somewhat drastically from Rails 4 to Rails 5, even changing names from “secrets” to “credentials”.
- I only need to use the feature once in a while, when I’m deploying an application for the first time, meaning there’s lots of time in between to forget everything I knew.
How to work with credentials without frustration
There are perhaps five important things to understand about credentials:
- Where they’re stored
- How the master key works
- How editing credentials work
- What the deal is with
secrets.yml
- The steps you need to take to set up credentials on a fresh production machine
- Take the same master key you’re using in development and put it either in
config/master.key
or theRAILS_MASTER_KEY
environment variable. - Set the
EDITOR
environment variable to your favorite terminal-based editor. - Run
rails credentials:edit
to verify that your master key is working properly. - Securing Rails Applications (official Rails guide)
- Rails 5.2. release notes
- DHH’s credentials pull request
- Stefan Wintermeyer’s credentials post
Credentials are stored in config/credentials.yml.enc
At the risk of stating the obvious, your secrets are stored in config/credentials.yml.enc
. That file is encrypted.
There of course needs to be a way to securely decrypt this encrypted file. That’s done using something called a master key. The master key is just a hash string that gets stored in one of two places: a file called config/master.key
(which should NOT be committed to version control) or a RAILS_MASTER_KEY
environment variable.
The development master key and production master key are the same by default
A key thing to understand, which I found counterintuitive, is that unless you go out of your way to configure it differently, the master key you use in production should be the same as the master key you use in development. If your development master key is stored in config/master.key
, create an identical config/master.key
on production, containing the same exact key. If your development master key is stored in the RAILS_MASTER_KEY
environment variable, set the production RAILS_MASTER_KEY
to the exact same value.
I found this counterintuitive because usually I try to make all my passwords, etc. different for each environment I have. I thought I would need to create a different master key for my production environment. No, I need to not create a different master key.
(After I originally posted this article, it was pointed out to me that it is possible to configure different keys per environment. According to this article, keys can be configured specific to e.g. production by running rails credentials:edit --environment production
.)
The credentials.yml.enc file is edited in a special way
Since it’s encrypted, the config/credentials.yml.enc
file can’t be edited directly. It can only be edited using the rails credentials:edit
command.
What often throws me for a loop is that a prerequisite to using rails credentials:edit
is having the EDITOR
environment variable set, which on a fresh production machine I usually don’t. I’m a Vim guy, so I run export EDITOR=vim
and then I’m good to go. Then I can run rails credentials:edit
and the command will open the credential file, decrypted, in Vim.
secrets.yml is obsolete
If you find something online that refers to secrets.yml
, you’re looking at an old post. Before Rails 5.2, there was a secrets.yml
and secrets.yml.enc
instead of the new credentials-related files. Don’t make the mistake of conflating Rails secrets with Rails credentials (like I did several times before learning better!).
The steps for setting up credentials in production
Helpful links
I hope my credentials guide is the new best guide on the internet but I’ll link to the sources that helped me put this together.
Best of luck with your credential management endeavors.
> The development master key and production master key are the same
No, you can have different keys, for different credentials files: https://github.com/rails/rails/pull/33521/files
CAN have different keys. Unless you go out of your way to make the keys different between development and production, they’ll be the same.
This post would benefit from having a section on how to use the credentials in rails code
Good point – I’ll plan to add it.
Another related post and a symmetric encryption library:
https://kig.re/2017/03/10/dead-simple-encryption-with-sym.html
Great simple explanation!
I’ve found Chamber (https://github.com/thekompanee/chamber) – and prefer it to Rails secrets.
Suppose you’re working on a team with multiple developers. And all of them need the ability to edit (or at least view) the `config/credentials.yml.enc` file. Given that the `master.key` file is gitignored, how could other developers have the ability to view the encrypted credentials file? (I’m assuming since it was originally encrypted with `master.key`, then only the developer that originally created the project with `rails new …` has access to the key)
I got very confused (actually still a bit confused) with the credentials files when I was using the dotenv gem. I had placed placed the development key as RAILS_MASTER_KEY
in the .env file, and then after some time, decided to regenerate the encryption keys. Usually when I did this, after performing the encryption, the master.key or test.key etc would be generated. This didn’t happen. I had to remove the entry in .env for the master.key to be created again. Another oddity, was, assuming that the .env entry was being used, I found that I could create the test, and development encryption files and they appeared to be using the same encryption key (I checked this by deleting the test.key and development.key, leaving only the .env entry)