Best place to check for env variables in Rails - ruby-on-rails

I use ENV variables for all environments to set up different components of the stack, i.e. Redis, Memcached, etc.
I load all of these in the config/application.rb file, and before that I ensure that all environment variables are present.
I'm running into a problem now where I run a rake task before these variables are set, and so it fails my test. Rake seems to doing it's share correctly. This leads me to believe all of these variables initializations are in the wrong spot.
Now I'm at a loss as to the best place to instantiate all these services or check for their existence.

Init them right after Bundler.require(*Rails.groups) in your application.rb like this https://github.com/bkeepers/dotenv#note-on-load-order
You can check env variables in Rails console, for example:
ENV['YOUR_ENV_VARIABLE']

Related

Specify environment variables for bundle exec

I have seen two different ways to specify environment variables when execute bundle exec. Which one is correct on Linux? Maybe both? I am looking for general answer, I know that in this particular case (updating Redmine) specifying RAILS_ENV may be even unnecessary.
bundle exec rake db:migrate RAILS_ENV=production
RAILS_ENV=production bundle exec rake db:migrate
Both options are possible to define environment variables for rake tasks. However, for other executables (such as the rails executable), only the variant to define the variables before the executable is supported.
What is happening here is that when you specify the environment variables at the start, your shell (bash, zsh, ...) set those environment variables for the newly started process. This can be done for any process. processes also inherit the environment variables defined earlier in the shell. A third option could thus be to run this in your shell:
export RAILS_ENV=production
bundle exec rake db:migrate
Now, if you specify the variables as arguments to the rake executable, the shell does not affect, read, or write those. Instead, rake itself inspects its given process arguments and sets the environment variables for its own process before handing control to the actual rake task (db:migrate in this case).
To be more consistent in your ability to define environment variables for the various executables, I personally tend to stick to the option to set environment variables in the shell, rather than using the rake feature to parse its arguments.
Finally, regarding your remark that the RAILS_ENV environment variable might not be necessary here: that is likely not true. Rails applications such as Redmine define different behavior based on the loaded environment, including the database they connect to (as defined in the config/database.yml file), other settings (as defined for Redmine in config/configuration.yml) and internal parameters such as logging verbosity and handling of exceptions. As such, you most likely want to always use RAILS_ENV=production everywhere since Rails (and Redmine) default to the development environment if nothing is specified.

Rails settings environment variables on production - explanation

I am trying to secure my app properly by setting environment variables. I am doing it with figaro gem. I am not using heroku, just a vps I setup by myself.
Now on development all works good and makes sense. application.yml contains hardcoded database passwords which are not on database.yml anymore. application.yml is not pushed on repository and passwords are not shared. All good.
But I am having hard time making sense of it on production. If I set production section on database.yml with environment variables and then the application.yml is not on the server running on production, how can it possibly work? Or if I set them on another file that is then pushed later on repository, I just moved harcoded passwords from a file to another and are still accessible. Or are environment varibales supposed to be used only on test and development?
Could someone give me a clear explanation? I have been reading other questions and articles around but I can't make sense of it.
You want to set Unix environment variables in production. Check out this guide which states:
Variables in the config/application.yml file will override environment variables set in the Unix shell.
In other words, in development you would set these variables in application.yml which would then override any values set in Unix. In production, you would set them in the shell and that is where the values would come from. I suggest doing some more general reading regarding environment variables as they are a fundamental part of application development.

How do you manage secret keys and heroku with Ruby on Rails 4.1.0beta1?

With the release of the secrets.yml file, I removed my reliance on Figaro and moved all of my keys to secrets.yml and added that file to .gitignore.
But when I tried to push to Heroku, Heroku said they needed that file in my repo in order to deploy the website. which makes sense, but I don't want my keys in git if I can avoid it.
With Figaro, I would run a rake task to deploy the keys to heroku as env variables and keep application.yml in the .gitignore. Obviously, I can't do that any more. So how do I handle this?
Secrets isn't a full solution to the environment variables problem and it's not a direct replacement for something like Figaro. Think of Secrets as an extra interface you're now supposed to use between your app and the broader world of environment variables. That's why you're now supposed to call variables by using Rails.application.secrets.your_variable instead of ENV["your_variable"].
The secrets.yml file itself is that interface and it's not meant to contain actual secrets (it's not well named). You can see this because, even in the examples from the documentation, Secrets imports environment variables for any sensitive values (e.g. the SECRET_KEY_BASE value) and it's automatically checked into source control.
So rather than trying to hack Secrets into some sort of full-flow environment variable management solution, go with the flow:
Pull anything sensitive out of secrets.yml.
Check secrets.yml into source control like they default you to.
For all sensitive values, import them from normal environment variables into secrets ERB (e.g. some_var: <%= ENV["some_var"] %>)
Manage those ENV vars as you normally would, for instance using the Figaro gem.
Send the ENV vars up to Heroku as you normally would, for instance using the Figaro gem's rake task.
The point is, it doesn't matter how you manage your ENV vars -- whether it's manually, using Figaro, a .env file, whatever... secrets.yml is just an interface that translates these ENV vars into your Rails app.
Though it adds an extra step of abstraction and some additional work, there are advantages to using this interface approach.
Whether you believe it's conceptually a good idea or not to use Secrets, it'll save you a LOT of headache to just go with the flow on this one.
PS. If you do choose to hack it, be careful with the heroku_secrets gem. As of this writing, it runs as a before_initialize in the startup sequence so your ENV vars will NOT be available to any config files in your config/environments/ directory (which is where you commonly would put them for things like Amazon S3 keys).
An equivalent for secrets.yml of that Figaro task is provided by the heroku_secrets gem, from https://github.com/alexpeattie/heroku_secrets:
gem 'heroku_secrets', github: 'alexpeattie/heroku_secrets'
This lets you run
rake heroku:secrets RAILS_ENV=production
to make the contents of secrets.yml available to heroku as environment variables.
see this link for heroku settings
if u want to run on local use like this
KEY=xyz OTHER_KEY=123 rails s

Accessing environment variables

I am setting the below environment variable.
ENV["RAILS_RELATIVE_URL_ROOT"] = "/prefix"
Is there any way of accessing this env variable other than ENV["RAILS_RELATIVE_URL_ROOT"]?
I know rails env can be accesses like Rails.env. Can all the env variables be accesses like that or is it something special for rails_env?
Rails.env only gives you the value of ENV["RAILS_ENV"] or ENV["RACK_ENV"]. If none of them were set, it returns "development".
The ENV object is provided by Ruby.
For another way to access it, you might consider either implementing it by yourself, or using the figaro gem. Set environment variables in a YAML config. Then they can be accessed like this:
Figaro.env.rails_relative_url_root

Heroku RACK_ENV remains “production”

I’ve set the environment variable RACK_ENV to staging via heroku_san’s configuration file (as well as manually).
When listing all ENV variables, it shows correctly as being set to "staging". If I check via the console I’m getting a correct result as well.
However, if I log it within my application_controller, it appears to be "production". Any idea why and how to correct this?
RAILS_ENV is set to "production". I’m guessing that this might cause the problem. Can’t these two differ from each other?
Rails looks for RAILS_ENV first, then for RACK_ENV. I guess, Heroku sets RAILS_ENV to production by default and it takes precedence over RACK_ENV. Try to set RAILS_ENV environment variable to "staging" directly.
And if that doesn't work, you should log ENV in your application controller, so that we can see what are all the environment variables from inside.

Resources