Active Storage Environment-Specific Credentials
Feb 13 2018Do you want to use the same storage service (e.g. S3, Azure, Google) for multiple environments with Active Storage?
Here is a solution using the new encrypted credentials and a small tweak to the Active Storage configuration file.
As I’ve been digging into Active Storage for one of my latest projects, I found myself wanting to use the same storage service (S3) for both development and production.
From reading the docs, it looks like the expectation is that most folks will use the local
storage service for development
and something like amazon
or google
for production
. This would probably work most of the time, for most people.
Conventional Scenario, Different Services Per Environment
This is how most folks will probably use Active Storage, using different storage service providers between development
and production
.
config/storage.yml
local:
service: Disk
root: <%= Rails.root.join("storage") %>
amazon:
service: S3
access_key_id:
<%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key:
<%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: us-east-1
bucket: app-bucket
config/environments/development.rb
Rails.application.configure do
config.active_storage.service = :local
end
config/environments/production.rb
Rails.application.configure do
config.active_storage.service = :amazon
end
rails credentials:edit
# /private/var/.../credentials.yml.enc.1234
aws:
access_key_id: 12345
secret_access_key: 67890
Let’s Try Another Approach
I usually prefer setting up development and test buckets on S3 for my local development to better mirror the staging and production environments locally. Here is how I did this using Active Storage and the new Credentials feature in Rails 5.2.
Same Service, Different Credentials, Different Environments
Changes to storage.yml
The main change to make this happen is to add some ERB goodness to the storage.yml
file, making it use the current environment when looking up the storage service information. Notice the dig
call now looks for an environment key as the scope for the actual AWS credentials.
config/storage.yml
amazon_<%= Rails.env %>:
service: S3
access_key_id:
<%= Rails.application.credentials.dig(
Rails.env.to_sym, :aws, :access_key_id) %>
secret_access_key:
<%= Rails.application.credentials.dig(
Rails.env.to_sym, :aws, :secret_access_key) %>
region: us-east-1
bucket: app-<%= Rails.env %>
Updating the environment configs
Now we just need to update the environment configs to point to amazon_development
and amazon_production
respectively.
config/environments/development.rb
Rails.application.configure do
config.active_storage.service = :amazon_development
end
config/environments/production.rb
Rails.application.configure do
config.active_storage.service = :amazon_production
end
Encrypted credential file changes
Then we just need to update our actual credentials to add the environment key scope to each of the credentials we want to use.
rails credentials:edit
# /private/var/.../credentials.yml.enc.1234
development:
aws:
access_key_id: dev-1234
secret_access_key: dev-5678
production:
aws:
access_key_id: prod-1234
secret_access_key: prod-5678
This approach embraces convention over configuration and allows each environment to use the same storage service, but different credentials for each environment.