Rail credentials, the master key

Rail credentials, the master key

My understanding of global vs environment master key file in Rails apps

I believe the concept and of rails credentials and the master key is meant to be simple. So simple, in fact, the documentation on it is a little sparse. This article is my understanding and experience dealing with master key and encrypted credential files.

When deploying a Rails application to a production environment, you'll need to at some point set up your encryption details, or your deployment will fail. The production environment will search for a RAILS_MASTER_KEY environment variable that matches the string in your local .key file. If the environment does not exist, or it does not match your .key file string, you'll find the deployment will fail.

Master Key and global vs environment specific credentials

This short, concise article titled "Rails Credentials can be Confusing" explains that you can have a global credentials file, or environment specific.

Global
------

# config/master.key                  # + .gitignore
# config/credentials.yml.enc

Environment specific
--------------------

Production
# config/credentials/production.key  # + .gitignore
# config/credentials/production.yml.enc

Development
# config/credentials/development.key # + .gitignore
# config/credentials/development.yml.enc

note *- You'll see that the .key files are added to the .gitignore file automatically. These files are just for your local machine. It's important that you do include the .yml.enc** files in your git repo, its safe because they're encrypted, and its where you store your encrypted credentials.

The production and development keys don't exist automatically, you need to run

rails credentials:edit -e production
rails credentials:edit -e development

And this will generate their .key and .yml.enc files.

The important thing to note here is that the environment specific credentials take precedence over the global credentials.

Below you will see an example of a real issue I was having until I found the above linked article which explained what was happening. In short, I did not have access to the credentials I was setting.

rails credentials:edit

--------
# config/credentials.yml.enc
username: shaun
password: abc123
--------

rails c

Rails.application.username
# => nil
Rails.application.password
# => nil

Why are they nil when I've set them using rails credentials? Because previously I have run rails credentials:edit -e development, and the development.yml.enc file is taking precedence over the global file (link to api docs explanation). I have not defined username and password in my development credentials.

So you have 2 options here

  1. Only use a global file
  2. Only use environment-specific files

I don't want to have to put the same credentials in two different files so I opt for the global configuration, meaning I should delete my whole config/credentials folder.

Setting the master key environment variable in production

If you don't set the environment variable RAILS_MASTER_KEY in production, you won't be able to deploy your app. You'll be met with an error looking something like

ActiveSupport::MessageEncryptor::InvalidMessage
...
Caused by:
OpenSSL::Cipherr::CipherError:
...

Using global credentials

cat config/master.key
# => xxxyyyzzz

Set the environment variable RAILS_MASTER_KEY=xxxyyzzz

Using environment specific credentials

cat config/credentials/production.key
# => 111222333

Set the environment variable RAILS_MASTER_KEY=111222333

Links