Heroku recommends not using a custom environment called staging
; instead, they suggest using the production
environment but with a different set of ENV
variables. This makes sense (see this question).
However, I am wondering how I can integrate this practice with Rails 6 encrypted credentials feature. Encrypted credentials does support multiple environments, so we can keep our development
and production
credentials separate; however, using Heroku's recommendation would mean that the production
credentials would be shared between the actual production server and the actual staging server. Which I don't want.
What I do want is the staging
server to use the development
credentials in the production
environment!
Keeping all the different credentials uploaded and up to date (between production, staging, and all our developers) is a hassle and the encrypted file seems like an much needed improvement; I just can't sort out how to get staging to use the non-production crednetials.
PS: perhaps one could override the config.credentials.content_path
per the docs based on an environmental variable set in Heroku that indicates whether to use the production or development credentials. Curious what others are doing or might do.
Overriding is the solution indeed. Here's my setup.
Since RAILS_ENV
is set to production
per Heroku's recommendation, I use another environment variable that I called PIPE_ENV
and which is set to the position in the pipeline, so staging
, edge
(for development), etc.
Now in application.rb
, I set the content_path.
module MyAppName
class Application < Rails::Application
…
if ENV["PIPE_ENV"].present?
Rails.application.config.credentials.content_path = Rails.root.join("config/credentials/#{ENV["PIPE_ENV"]}.yml.enc")
end
end
end
I don't like having things in here but config/environments/production.rb
uses credentials to set the mailer, so it has to be set earlier.
Also, don't forget to set the RAILS_MASTER_KEY to the corresponding environment, so for staging you call
heroku config:set RAILS_MASTER_KEY=your-staging-key -a your-staging-app
Of course, your-staging-key
is the string in config/credentials/staging.key
Bonus, for the rest of your app, you can add this in config/initializer/pipe_env.rb
so that you can call Rails.pipe_env
just like you call Rails.env
:
module Rails
class << self
def pipe_env
@_pipe_env = ActiveSupport::StringInquirer.new(ENV["PIPE_ENV"].presence || Rails.env)
end
end
end