This post is part of the Zero-downtime with Rails credentials series.
In the first post we talked about the reasons that moved us towards making a codewide change and adopt Rails credentials rather than using environment variables to manage our secrets.
In the second post we saw what that means to us in our codebase in practice, and how to structure the files necessary to use Rails credentials in each environment within our application.
We left you hanging with a big question, whether we still need an .env
file after all.
Here’s the answer…
Credentials don’t fully replace .env
In an ideal world we would not need to have a .env
file at all.
When we originally started this task, we thought credentials would replace environment variables in their entirety.
However, as you may have already guessed, at the very least we need 2 environment variables even when using credentials:
RAILS_ENV
RAILS_MASTER_KEY
RAILS_ENV
tells the application which environment it is when it loads
and guides the application towards the correct credentials file for
that environment.
RAILS_MASTER_KEY
allows Rails to decrypt the credentials.
Without these 2 environment variables, Rails would not be able to infer which credential file to use and how to encrypt it.
Load Differences
We may also have other environment variables that still need to
be defined apart from RAILS_ENV
and RAILS_MASTER_KEY
.
This is because environment variables are available when the app loads at an earlier stage than Rails Credentials.
This is one of the drawbacks of Rails Credentials, unlike environment variables, they live within the application, so they require the application to load before they are available to use.
Therefore, some environment variables that we use during the loading of the application may need to remain as environment variables.
These are mainly in files that live in config/
or initializers/
.
OK, well, surely if we still have .env
files then we can’t use hot reloading and achieve zero-downtime?
Don’t worry, we can, and we will!
The only issue with using hot reloading with environment variables is that hot reloading does not pick up any changes to those environment variables.
However, we have now distilled our .env
files to only house
minimal environment variables that we do not expect to change and
should not change.
The vast majority of key value pairs have moved to credentials and changes to them will be reflected with hot reloading puma.
However, if for some reason, we did make a change to an environment variable then we would need to restart the puma server for this change to be picked up.
Where do I put things going forward in .env
or credentials?
It’s a great question!
We think that by default we should always endeavour to use Rails Credentials. This protects us from being able to change the values without having downtime and also has the added benefit of storing things inside the application which will be easier to manage.
However, if you are adding something that needs to read before the
credentials have loaded than you can add it to the .env
file.
Now that we have Rails credentials in our application, we want to explore how to use them in our test suite. Stay tuned for the next article, about stubbing Rails credentials in specs and other caveats.