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 by default. For applications created prior to Rails 5.2, we’ll automatically generate a new
credentials file in 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 .

Here is an example of

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.

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 keys and put all needed under the related key.
  2. Override method on Rails application.

Top-level Hash as an environment key.

Fetching value in the code will be through a call on

Override method on Rails application.

This uses the default credentials file if the Rails environment is . 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 command supports passing an option to create an environment-specific override file with variables. That override will take precedence over the global file when running in that environment.

Let’s create an example for the development environment:

This task will create with the new encryption key in

Let’s add our keys here:

To get the value just use

Encrypted secrets for non-Rails applications

Gem 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.

Encrypted secrets with Rails older than 5.0

Add to of Rails project:

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

Keep your secret key into file:

Now you can edit them with the following task:

Add this line to which will load secrets for the current environment

To get the desired value use

Encrypted secrets with pure Ruby apps (non-Rails)

Add to of Ruby project:

Here is an example of a secret reader class for a rack-based env variable . 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 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.