Switching from ENV files to Rails Credentials

Struggles I had with ENV files

Tell me if you’ve heard this one before. You join a new project, run through all the steps on the README and you’re finally ready to run it locally… but then something goes wrong, and you realize you’ve been missing the ENV file. That could happen because, even though we have environment specific ENV files, even then they might contain sensitive information that can’t be displayed publicly.

While not having those files on a VCS is a good practice, it creates another problem: where do you store them? Eventually, someone new will come around and need to get that same file with all those keys. Or perhaps a developer is integrating a new API, and they need to add a new key to the ENV file. How do you ensure all of the people contributing to the project get an updated version? And how do you effectively keep track of all environment-specific values? I’ve been in these situations many times over the past few years, and let me tell you, it’s terrible. Hence, I wanna share something really cool I learned the other day and why I think it’s a better solution: Rails Credentials.

Fixing those struggles with Credentials

Previously called secrets, credentials is nothing more than an encrypted YAML file built in Rails for storing, well, credentials. Stored in config/credentials.yml.enc, Rails uses a key stored in config/master.key to encrypt and decrypt the file, making sure that you can actually version-store your environment variables (but don’t commit your key!). This makes it easier for both of the examples previously mentioned: instead of having to give new developers a whole file with many variables, you can provide them with the key, and when the credentials are updated other developers will literally have to do nothing more than update their branch with the latest changes.

So instead of storing, let’s say, a Google Maps API key in an ENV file, you could store it in your credentials. To do that, simply run the command to open the encrypted credentials file and put your key there:

EDITOR="code --wait" bin/rails credentials:edit

Inside the file you should just follow standard yml notation:

google_maps_key: a_secret_key_that_no_one_will_ever_know_hopefully

It may take a while for it to open, since Rails will have to decrypt the file before using it. Notice that I used the argument EDITOR, which allows you to choose which editor you want to open it with, so feel free to change it to your favorite one. To access the stored keys, in this example google_maps_key, run:

Rails.application.credentials.google_maps_key

Another cool feature about credentials is that you can separate them by environment, and each one will have a different master key. This helps us to keep track of the different versions you have, and also to control who has the privilege to edit each environment. To edit the production environment, use:

rails credentials:edit --environment production

While this doesn’t completely erase the need to keep track of who has access to what, and environment variables in general, it certainly makes it easier. For example, instead of having to give your deploy service every single private key you’ll ever need, you just give it the encryption key. And as always, every product has it’s own needs, so there may be a case when using credentials may actually be a disadvantage. For example, when you have a different framework than Rails on the same repo that needs access to similar keys. So consider this just another approach to an existing problem.

If you want to dive deeper into this topic, check out these links: