Encrypted Secrets(Credentials) in Rails 6, Rails 5.1/5.2, older versions and non-Rails applications

How to manage encrypted keys for different environments

There are two most popular ways to manage secrets in your application.

  1. Encrypted file with secrets. Best choice for a single monolith application. There’s no need for additional software, just keep your encrypted data in the app repository and move decrypt key under git ignore.
  2. Centralized storage. For large and complex systems it’s better to use dedicated storage for all services and provide an interface for them. Vault is a cool example of this kind of solution.

In this article, I want to talk about the first approach.

Encrypted secrets were first introduced in Rails 5.1. Rails store secrets in config/credentials.yml.enc by default. For applications created prior to Rails 5.2, we’ll automatically generate a new
credentials file in config/credentials.yml.enc the first time you run:

If you don’t have a master key, that will be created too. Applications after Rails 5.2 automatically have a basic credentials file generated that already contains the secret_key_base.

Here is an example of config/credentials.yml.enc

And this is how to get value from credentials:

Below I’ll list three cases of managing encrypted variables: Rails 6, Rails 5.1/5.2, older versions and non-Rails applications.

Image for post
Image for post

Rails 5.1.x and 5.2.x: Single file for all environments

This was the main problem. One single file with all credentials and one single key for them. There is no way to share access between developers for a specific environment. Though you can easily hack a naming problem in two ways:

  1. Adding dev, staging, production keys and put all needed under the related key.
  2. Override credentials method on Rails application.

Fetching value in the code will be through a call Rails.env on Rails.application.credentials

This uses the default credentials file config/credentials.yml.enc if the Rails environment is production. With this solution decrypt key can be specific for each environment.

Rails 6: Specify And Manage credentials file for each environment

So, now Rails 6 supports Multi Environment Credentials.

The credentials command supports passing an--environment option to create an environment-specific override file with variables. That override will take precedence over the global config/credentials.yml.env file when running in that environment.

Let’s create an example for the development environment:

This task will create config/credentials/development.yml.enc with the new encryption key in config/credentials/development.key

Let’s add our keys here:

To get the value just use Rails.application.credentials

Encrypted secrets for non-Rails applications

Gem sekrets is the most flexible solution I’ve worked with. It works just fine for any kind of Ruby app. Even rails encrypted secrets were based on this.

Add to Gemfile of Rails project:

Then create an encrypted config file (for each needed environment)

Keep your secret key into .sekrets.key file:

Now you can edit them with the following task:

Add this line to config/application.rb which will load secrets for the current environment

To get the desired value use Rails.configuration.sekrets

Add to Gemfile of Ruby project:

Here is an example of a secret reader class for a rack-based env variable RACK_ENV . Just replace it, if you have another environment id.

The process of creating and editing a file with variables is identical for Rails older than 5.x. To receive values just call Secret class. But first of all this file should be required globally or in a used location.

Conclusions

  • Separate encryption key for each environment. Do not create a single key for all environments. It is safer to have separate keys for CI, development, and production
  • Encrypted secrets make easier deploys. Variables can now be shipped with the code. You only need to upload the key to the server once.
  • This solution can be used for any kind of Ruby or Rails application.

Software Engineer. Interested in Full-Stack Development and DevOps.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store