Linux gives us environment variables, which is a collection of variables that are globally available, but specific to that shell instance, so they need to be set every time you create a new terminal instance; they do not persist from one terminal instance to another. They are used for a million different things: from setting the basic settings of our shell to configurations for the applications that we build ourselves.
In terminal, we can access the environment variables of our shell via the ‘env’, ENV
, or ‘printenv’ command.
In our Rails code, the terminal’s environment variables can be referenced via the ENV
variable. Unlike the env variable in the terminal, the one in Rails is case sensitive - it must be upper case.
Pre-5.2, secrets work like this:
We have a config/secrets.yml
file. Technically, you could put all of your secrets directly here. But by convention, this file was used more as a liason between your rails code and the linux runtime environment that your app was running in, and which contained your secrets, stored in environment variables. In other words, this file does not hold the actual values of your secrets/environment variables; it only holds the names of those secrets, and retrieves the actual values from ENV. This file gets committed to version control and is visible to anyone with access to the codebase. It allows for the application to access secrets through the Rails.application.secrets
interface, instead of having to directly access the ENV from a thousand different places throughout the app. This approach also has the advantage of neatly documenting all of your secrets/configurations without exposing their values.
The actual “secret values” themselves only live in your local ENV, or, if you are using the dotenv gem, they live in your .env file, from where they are loaded into your ENV, and from where they are picked up by the config/secrets.yml
file.
In production, the ENV is populated by some method or another - it’s usually specific to which platform or cloud provider you are using. (Dotenv is only really meant for use in development.) But either way, once the ENV is populated, the propagation of the secrets through the system works pretty much identically as in development.
Starting in Rails 5.2, secrets work like this:
The whole system for how credentials are managed is different. The dependency on linux environment variables is gone. No longer will devs have to set a bunch of variables in their environment. Rather, the way things work now is that the creds are written out in a file (that will not be committed to source control) as part of the Rails app, and that file is then encrypted with a master key. The encrypted file is committed to source control, but the master key is not, and you need the key to be able to read or edit the credentials. So the credentials, through the magic of encryption, are up there on Github for anyone to see, but not readable or editable. This makes dealing with secrets between environments much easier, because instead of having to deal with a bunch of secrets, you just have to deal with one master key, stored in config/master.key
.
David Kennell is a web developer, specializing in Ruby on Rails, Javascript, and React. His most recent tech-related interests are DNS and database normalization. In his free time he enjoys not making up a list of hobbies for his blog bio. :D