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:
- Rails Official Security Guide
- Rails 6 adds support for multi-environment credentials
- Handling Secrets and environment variables in Rails
Let’s work together!
Looking for a partner to help with your project? Let’s chat about how we can collaborate together on bringing your ideas to life.