Storing Secret Credentials in Rails 5.2 and Up
Aatif Jiwani, Former Rails Developer Intern
Keeping your credentials safe as a developer is extremely important. You don’t want to commit any sensitive information, like passwords or API keys, to your remote git repository as it can allow malicious users to access the services you are using.
The Good Ol’ Days #
Since version 4.1, Rails has helped developers store their secrets by generating a new
secrets.yml file in the config folder. By default, this file contains a
SECRET_KEY_BASE that is used to “derive keys for encrypted cookies… [and] HMAC signed cookies.” However, you could add additional keys to this file:
# config/secrets.yml development: secret_key_base: n3mb3r5a5ndl3t4ter5 secret_api_key: SOME_PRIVATE_KEY
Once everything is saved, you could access it via
Rails.application.secrets.secret_api_key. This way, you could store your secret credentials in a single file and simply make sure that
secrets.yml is part of your
The release of Rails 5.1 added another file named
secrets.yml.enc to allow for encrypting your secret credentials, but this caused some confusion. The combination of
SECRET_KEY_BASE made it so it wasn’t clear where secrets should be stored and what the relevance of
SECRET_KEY_BASE was  .
A New Beginning #
With this confusion in mind, Rails released version 5.2 and created an entirely new way to store your secret credentials that I will walk you through.
First, make sure you install the newest version of Rails by running:
gem update rails
This ensures that the Rails Gem you install is the most up to date (you can find the most recent release of Rails on the official RubyGems page). After doing so, when you create a new Rails project, you should see two files in your config folder:
credentials.yml.encis an encrypted file that will contain all your secret credentials. Your private API keys and passwords will all be stored in this file, all encrypted. Since this file is encrypted, it is safe to push this to a remote git repository or a server.
master.keyis a file containing your encryption key. Without this file or if it is modified, Rails will not be able to read your credentials stored in
credentials.yml.enc. This file should NOT be pushed to a git repo or any server as it can be used to decrypt
credentials.yml.encand someone can steal sensitive information.
You must be wondering, how do I add my secret credentials to
credentials.yml.enc if it is encrypted? Well, you need to go into your command line interface and run:
EDITOR="subl --wait" bin/rails credentials:edit
--wait flag, your
credentials.yml.enc will be saved immediately without giving you the chance to edit. Also, you can replace “subl” with the command line shortcut to whatever your favorite text-editor is (in this case, the command above will open
credentials.yml.enc in Sublime since I’ve made the shortcut available). Now, you can edit and store new credentials in YAML format, save the file, and Rails will automatically re-encrypt
credentials.yml.enc for you. You can access these secret credentials at any point in your application by using:
And you’re good to go! If you do not want to redefine your
EDITOR everytime you want to edit your credentials, simply add to your shell profile:
export EDITOR="subl --wait"
Now, all you need to do to edit your credentials is run:
Heroku and other Deployment Strategies #
If you’re deploying your app to Heroku, the encryption key from
master.key is stored in an entirely different way. Heroku allows you to add special configuration variables in the Settings tab of your app’s dashboard. There, you can add a new config variable called
RAILS_MASTER_KEY and paste the encryption key into the space provided. Once saved, the Rails application is smart enough to detect that the master key is stored as a config variable to decrypt your secret credentials.
The underlying technology of this method is that Heroku is setting an environment variable that Rails can access via
ENV[“RAILS_MASTER_KEY”]. Therefore, to store your master key on other remote servers, you just have to save the encryption key as an environment variable.
What if you need to share your
master.key with other developers working on your team or project? Simply sending a message containing the special key over spaces like Slack isn’t safe and ultimately isn’t good practice. That’s why password management is a giant field of its own and there are a multitude of ways to securely share your credentials with trusted people. Two services I personally use are 1Password and OneTimeSecret.
1Password is a secure password manager that allows users to store any kind of credentials: passwords, API keys, software licenses, etc. In fact, 1Password allows organizations to get in on it so team members can securely share a pool of sensitive information amongst everyone on their team.
OneTimeSecret is more for quickly sharing credentials with your team and less for long-term storage like 1Password. You can generate a secret link, password-protected or not, that will contain the sensitive information once opened. However, there’s a catch! Once you open the link for the first time, you should store the given information somewhere more secure as you cannot open the link ever again. Also, the secret-holder can set an expiry time on the link so you have a certain timeframe to retrieve the secret information and store it in another location.
Now, you know how to safely store credentials and reduce the risk of unauthorized access!