Rails 5.2 credentials

As announced in Rails 5.2.0 release candidate, Rails 5.2 will go out with a brand new credentials API that will eventually replace the current config/secrets.yml and config/secrets.yml.enc.

The intention behind this change is mainly to remove some of the confusion introduced by the combinations of config/secrets.yml, config/secrets.yml.enc and SECRET_BASE_KEY used in earlier versions of Rails, and attempt to unify everything using a more straightforward approach.

From now on, Rails 5.2 will only intend to use these two files instead:

  • config/credentials.yml.enc
  • config/master.key

Using new Rails credentials

When you upgrade Rails to v5.2, the file where you are going to store all your private credentials is config/credentials.yml.enc.

As it’s extension suggests, this file is going to be encrypted - so you won’t be able to read what’s inside of it - unless you have the proper master key to decrypt it. This is why it IS safe to version this file into your source control tool.

The second file, config/master.key, is the file where your RAILS_MASTER_KEY will be placed.

The RAILS_MASTER_KEY is the key that Rails will use to decrypt your config/credentials.yml.enc. It is NOT a good idea to version config/master.key file into your source control tool. You need to keep it as a secret, so make sure to list it in your .gitignore file if you’re using git.

Editing Credentials

Since it’s encrypted, Rails 5.2 comes with a way to edit the config/credentials.yml.enc file. You can do that by running the following command:

EDITOR=vim rails credentials:edit

This will open up a vim editor with the decrypted version of the file (you can use others editors too, not necessarily vim). When you save it, it will encrypt it again using your master key.

You’ll see that the decrypted version of the file looks like any other normal .yml file.

By the time you run the credentials:edit command, If config/master.key and config/credentials.yml.enc don’t exist, Rails will take care of creating them on your behalf.

Reading credentials

Let’s assume that the unencrypted version of your config/credentials.yml.enc file looks like this:

aws:
access_key_id: 123
secret_access_key: 345
secret_key_base: 2fdea1259c6660852864f9726616df64c8cd

Then, you should be able to access the configuration programmatically like this:

Rails.application.credentials.aws[:access_key_id]     # => "123"
Rails.application.credentials.aws[:secret_access_key] # => "345"
Rails.application.credentials.secret_key_base # => "2fdea...

Credentials & Environments

The Rails team is proposing to remove the environment scopes inside config/credentials.yml.enc.

This new file is a flat format, not divided by environments, like secrets.yml has been. Most of the time, these credentials are only relevant in production, and if someone does need to have some keys duplicated for different environments, it can be done by hand. [DHH]

Nevertheless, you can always edit config/credentials.yml.enc and add namespaces for your secrets under development, test or production like the ones you would have in the old config/secrets.yml. You can structure your config/credentials.yml.enc like this:

development:
aws:
access_key_id: 123
secret_access_key: 345
secret_key_base: 2fdea1259c6660852864f9726616df64c8cd
production:
aws:
access_key_id: 321
secret_access_key: 543
secret_key_base: hu23ih41iu23h4123u4h23iu4h2323j412i3

Then, simply add the environment namespace when you access the configs:

Rails.application.credentials[Rails.env.to_sym][:aws][:access_key_id]

Deploying master key

When you move your code to a server, you need to make sure that your config/credentials.yml.enc file can be decrypted. That means that somehow you’ll need to provide Rails with your master key, given that it is not checked into version control.

There are two ways of doing that:

  • Option 1: Place the config/master.key file in the server. You’ll normally want to symlink this file to a shared folder in the server filesystem. Again, do not version your config/master.key file.
  • Option 2: create a RAILS_MASTER_KEY ENV variable. Rails will detect it and use it as your master key, e.g. in heroku: heroku config:set RAILS_MASTER_KEY=<your-master-key-here>.

You should be able to use any of those indistinctly.

Upgrading from previous Rails

Keep in mind that the config/secrets.yml and config/secrets.yml.enc will continue to work and will still be compatible with Rails 5.2

Note: We will just keep Rails.secrets and friends around. The Rails.application.credentials setup will be a new, concurrent approach. All new apps would use it, but we wouldn’t need to screw existing apps. [DHH]

That won’t be forever though, so it’s not a bad idea to think about upgrading soon.

If you are upgrading your app, and not starting from a brand new Rails 5.2 app, make sure to add the following configuration to your config/environments/production.rb file:

config.require_master_key = true

This will tell Rails to ensure that a master key has been made available from either ENV['RAILS_MASTER_KEY'] or in config/master.key.

Conclusion

In general, I understand what the motivation behind this change is and I support it. If the old approach was confusing for a lot of people I believe it’s a good thing that the Rails team tries to improve it. Hopefully people will adopt it and it will become the standard for everyone.

If you want to read more about this, you can take a look at DHH’s Pull Request for the initial description and implementation of the change.