Search code examples
ruby-on-railsenvironment-variablesruby-on-rails-5amazon-elastic-beanstalk

Rails 5 reads environment variables as string in YAML file


I have a Rails 5 app and I am trying to import my Environment Variables in a yaml file, which I can then import in the environment.rb. My config/aws.yml looks as follows:

S3_BUCKET: <%= ENV["S3_BUCKET"] %>
AWS_ACCESS_KEY_ID: <%= ENV["AWS_ACCESS_KEY_ID"] %>
AWS_SECRET_ACCESS_KEY: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

Then in my environment.rb I have the following:

require_relative 'application'
aws_file = File.join(Rails.root, 'config', 'aws.yml')
if File.exist?(aws_file)
  YAML.safe_load(File.open(aws_file)).each do |k, v|
    ENV[k.to_s] = v
  end
end

on running my rails c this is what I get:

[1] pry(main)> ENV.fetch('S3_BUCKET')
=> "<%= ENV[\"S3_BUCKET\"] %>" 

How can I pass the actual environment variable rather than it pulling the name of the environment variable as a string?

EDIT: Adding more relevant information

My credentials are stored in my elastic-beanstalk configuration and I am trying to load the values from the configuration to my yaml file.


Solution

  • <%= ... %> is a feature of ERB, not YAML. You'd need to first run your YAML file through ERB to cause the <%= ... %> to execute and then load it as YAML.

    But there's a deeper problem. Your YAML file is trying to get its values from environment variables. But then you set those same environment variables from the YAML values. It's circular.

    Instead use something like Encrypted Credentials introduced in Rails 5.2 to manage your secrets. Then write config/initializer/aws.rb to set the necessary environment variables from those secrets. This is nice because it stores your secrets in your app rather than in the deployment platform. Then it can be run with full secrets anywhere.

    Or you can set the environment variables in Elastic Beanstalk via the "Environment Properties" console.