bashrc environment variables not working with Rails app - ruby-on-rails

I have setup variables in my ~/.bashrc file that I would like to use with my Rails app. The problem is Rails will not recognize these variables.
bashrc:
export MYSQL_DB_USERNAME=admin
export MYSQL_DB_PASSWORD=testing123
Rails app - database.yml
username: <%= ENV["MYSQL_DB_USERNAME"] %>
password: <%= ENV["MYSQL_DB_PASSWORD"] %>
If I go into the rails console and type:
ENV["MYSQL_DB_USERNAME"]
I get back: <= nil
I've reloaded my bashrc file and restarted the terminal. Neither worked. Why won't Rails read these variables from the bashrc file?
(I am using RVM for ruby version management, in case that matters).
Thanks.

You can put your setting at the top of ~/.bashrc.
Because mina uses ssh in non-interactive mode.
In the first files of .bashrc, it has
#If not running interactively, don't do anything
[ -z "$PS1" ] && return
The settings below this line will be ignored.

It depends on how you are running the rails app.
For example if you did
export MYSQL_DB_USERNAME=admin
export MYSQL_DB_PASSWORD=testing123
rails console
> ENV["MYSQL_DB_USERNAME"]
Then most likely your code would work. If you are starting the railsapp as a different user, or as a daemon/service, then it won't share the same environment and the environment variables you created won't be set anymore.
In my opinion, the best way to set variables is to create a yaml config file. You can do /etc/myapp/config.yml and inside it set the following
MYSQL_DB_USERNAME: admin
MYSQL_DB_PASSWORD: testing123
This should be more cleaner than storing the user_name/password inside your .bashrc file since you can allow only the rails user to reading this through file permissions - you don't want to play with the file permissions of your .bashrc.

Related

how to add environment variable in linux for rails app?

i need to set an environment variable for the rails app to use
SECRET_KEY_BASE=9941144eb255ff0ffecasdlkjqweqwelkjasdlkjasd
the config settings for production is as shown below
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
how can i set the environment variable using the linux command
export VARNAME="my value"
I tried to set the variable but looks like it needs to be for the right user. Sorry i am not an expert in linux.
I appreciate any help! Thanks!
export VARNAME="my value"
Well the above works for your current terminal session. After this command, all the subsequent commands can access this variable. Try running this:
echo $VARNAME
It will print the value my value in the console. If you want this behaviour to be persisted, you need to place the export command in your OS' config file (~/.bashrc in case of Ubuntu).
After editing this file, either restart your terminal, or run this:
source ~/.bashrc
This will reload the file in your current terminal session. Alternatively, you can try running your Rails server (or a rake command) as follows:
VARNAME="my value" rails s
For your local development I suggest you to use dotenv (https://github.com/bkeepers/dotenv) or figaro (https://github.com/laserlemon/figaro) and follow the README you find in the gem itself. This gives you much more flexibility than using directly environment variables because you set them only for this specific project and each project can have different of them.
You need to have either a .env file or a application.yml file where you will define your environment variables.
Remember to not commit or push this file to your repository because it contains sensible information!
When you will deploy to production you can use real environment variables or use admin panel control (on Heroku for example)

Where is SECRET_KEY_BASE environment variable located when I start Rails app in Production

In the Rails 4 In Action Book, it states that after doing some other setup: the final setup to boot up your rails app in production mode (with web brick) is to enter this command in terminal:
SECRET_KEY_BASE='rake secret' rails s -e production
I am trying to see where the environment variable of SECRET_KEY_BASE is stored.
Within /app/config/secrets.yml it says that the secret_key_base variable is an environment variable:
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
But I looked within .bashrc and .bash_profile and the variable SECRET_KEY_BASE is not there.
Ultimately I want to know: where is environment variable and its value? Is it stored somewhere in my rails app? I hope not for security purposes if I push this app to github. I assume it is not stored in the app but in my computer system somewhere. Within a different terminal window I do echo $SECRET_KEY_BASE but nothing gets returned.
Thanks in advance for helping me understand the missing pieces.
As a side note: I am aware of this question, but the question is not as detailed and there is no provided answer.
When you run this:
SECRET_KEY_BASE='rake secret' rails s -e production
you are not actually 'saving' the secret key for future you. You're defining it on a one-time basis. Whenever you run a Ruby command you can set temporary environment variables:
# from shell
KEY="VAL" OTHER_KEY=OTHER_VAL ruby my_command.rb
# from the ruby script
puts ENV["KEY"] # => "VAL"
puts ENV["OTHER_KEY"] # => "OTHER_VAL"
To persist the environment variables you have a couple options. You could hard code them in your source code, but this is probably not a good idea because if you push your code to Github, anyone will be able to see it. That's kind of the point of environment variables, anyway, that you can keep them system specific.
Option A
You can set them in .bashrc or .bash_profile
First get the result of rake secret (will be a random string) and set a shell variable:
KEY=`rake secret` # uses backticks to get command result
Then add a line in bashrc to export it:
echo -e "export SECRET_KEY_BASE=$KEY" >> ~/.bashrc
Option B
This is the one I'd recommend, you can use dotenv or figaro to manage your environment variables in an app-specific way, i.e. without cluttering up your bashrc.
For example with dotenv you'd create a .env file which contains:
# change this to the result of rake secret
SECRET_KEY_BASE=j3e2dd293d
This would be excluded from source control by adding it to gitignore.
Then in your ruby app you call
require 'dotenv'
Dotenv.load
and your ENV["SECRET_KEY_BASE"] will be set.
If you want you can make a .env.example file (included in source control) which shows which environment variables need to be defined. Then when the app is cloned you can run mv .env.example .env and customize .env.

Environmental variables in /etc/environment are not accessible by rails

I have been trying to deploy a rails project and it requires some environmental variables so I did some research and it turns out the best place to add them is inside /etc/environment which i did so and then sourced the file.
I now can get/access the environmental variables by running echo $variablename; however the rails application can still not see these environmental variables?
/etc/environment is not automatically sourced by all shells in all login contexts. To get the settings into the rails environment, there are a couple options. The easiest is probably to modify (or create) the .bashrc (assuming the rails user's shell is bash, which is the Ubuntu default shell) in the home directory of the user rails runs as and add the following line:
source /etc/environment
If you want the variables to be available to all users on the system, you can create a file called /etc/profile.d/environment.sh (or something similar) and add the above line to that.
For either solution, log in again as the rails user and verify the environment.
You might want to use this gem for env variables:
https://github.com/bkeepers/dotenv

How to solve error "Missing `secret_key_base` for 'production' environment" (Rails 4.1)

I created a Rails application, using Rails 4.1, from scratch and I am facing a strange problem that I am not able to solve.
Every time I try to deploy my application on Heroku I get an error 500:
Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`
The secret.yml file contains the following configuration:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
On Heroku I configured the "SECRET_KEY_BASE" environment variable with the result of the rake secret command. If I launch heroku config, I can see the variable with the correct name and value.
Why am I still getting this error?
I had the same problem and solved it by creating an environment variable to be loaded every time I logged in to the production server, and made a mini-guide of the steps to configure it:
I was using Rails 4.1 with Unicorn v4.8.2 and when I tried to deploy my application it didn't start properly and in the unicorn.log file I found this error message:
app error: Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml` (RuntimeError)
After some research I found out that Rails 4.1 changed the way to manage the secret_key, so if you read the secrets.yml file located at exampleRailsProject/config/secrets.yml you'll find something like this:
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
This means that Rails recommends you to use an environment variable for the secret_key_base in your production server. In order to solve this error you should follow these steps to create an environment variable for Linux (in my case Ubuntu) in your production server:
In the terminal of your production server execute:
$ RAILS_ENV=production rake secret
This returns a large string with letters and numbers. Copy that, which we will refer to that code as GENERATED_CODE.
Login to your server
If you login as the root user, find this file and edit it:
$ vi /etc/profile
Go to the bottom of the file using Shift+G (capital "G") in vi.
Write your environment variable with the GENERATED_CODE, pressing i to insert in vi. Be sure to be in a new line at the end of the file:
$ export SECRET_KEY_BASE=GENERATED_CODE
Save the changes and close the file using Esc and then ":x" and Enter for save and exit in vi.
But if you login as normal user, let's call it "example_user" for this gist, you will need to find one of these other files:
$ vi ~/.bash_profile
$ vi ~/.bash_login
$ vi ~/.profile
These files are in order of importance, which means that if you have the first file, then you wouldn't need to edit the others. If you found these two files in your directory ~/.bash_profile and ~/.profile you only will have to write in the first one ~/.bash_profile, because Linux will read only this one and the other will be ignored.
Then we go to the bottom of the file using Shift+G again and write the environment variable with our GENERATED_CODE using i again, and be sure add a new line at the end of the file:
$ export SECRET_KEY_BASE=GENERATED_CODE
Having written the code, save the changes and close the file using Esc again and ":x" and Enter to save and exit.
You can verify that our environment variable is properly set in Linux with this command:
$ printenv | grep SECRET_KEY_BASE
or with:
$ echo $SECRET_KEY_BASE
When you execute this command, if everything went ok, it will show you the GENERATED_CODE from before. Finally with all the configuration done you should be able to deploy without problems your Rails application with Unicorn or some other tool.
When you close your shell and login again to the production server you will have this environment variable set and ready to use it.
And that's it! I hope this mini-guide helps you solve this error.
Disclaimer: I'm not a Linux or Rails guru, so if you find something wrong or any error I will be glad to fix it.
I'm going to assume that you do not have your secrets.yml checked into source control (ie. it's in the .gitignore file). Even if this isn't your situation, it's what many other people viewing this question have done because they have their code exposed on Github and don't want their secret key floating around.
If it's not in source control, Heroku doesn't know about it. So Rails is looking for Rails.application.secrets.secret_key_base and it hasn't been set because Rails sets it by checking the secrets.yml file which doesn't exist. The simple workaround is to go into your config/environments/production.rb file and add the following line:
Rails.application.configure do
...
config.secret_key_base = ENV["SECRET_KEY_BASE"]
...
end
This tells your application to set the secret key using the environment variable instead of looking for it in secrets.yml. It would have saved me a lot of time to know this up front.
Add config/secrets.yml to version control and deploy again. You might need to remove a line from .gitignore so that you can commit the file.
I had this exact same issue and it just turned out that the boilerplate .gitignore Github created for my Rails application included config/secrets.yml.
This worked for me.
SSH into your production server and cd into your current directory, run bundle exec rake secret or rake secret, you will get a long string as an output, copy that string.
Now run sudo nano /etc/environment.
Paste at the bottom of the file
export SECRET_KEY_BASE=rake secret
ruby -e 'p ENV["SECRET_KEY_BASE"]'
Where rake secret is the string you just copied, paste that copied string in place of rake secret.
Restart the server and test by running echo $SECRET_KEY_BASE.
While you can use initializers like the other answers, the conventional Rails 4.1+ way is to use the config/secrets.yml. The reason for the Rails team to introduce this is beyond the scope of this answer but the TL;DR is that secret_token.rb conflates configuration and code as well as being a security risk since the token is checked into source control history and the only system that needs to know the production secret token is the production infrastructure.
You should add this file to .gitignore much like you wouldn't add config/database.yml to source control either.
Referencing Heroku's own code for setting up config/database.yml from DATABASE_URL in their Buildpack for Ruby, I ended up forking their repo and modified it to create config/secrets.yml from SECRETS_KEY_BASE environment variable.
Since this feature was introduced in Rails 4.1, I felt it was appropriate to edit ./lib/language_pack/rails41.rb and add this functionality.
The following is the snippet from the modified buildpack I created at my company:
class LanguagePack::Rails41 < LanguagePack::Rails4
# ...
def compile
instrument "rails41.compile" do
super
allow_git do
create_secrets_yml
end
end
end
# ...
# writes ERB based secrets.yml for Rails 4.1+
def create_secrets_yml
instrument 'ruby.create_secrets_yml' do
log("create_secrets_yml") do
return unless File.directory?("config")
topic("Writing config/secrets.yml to read from SECRET_KEY_BASE")
File.open("config/secrets.yml", "w") do |file|
file.puts <<-SECRETS_YML
<%
raise "No RACK_ENV or RAILS_ENV found" unless ENV["RAILS_ENV"] || ENV["RACK_ENV"]
%>
<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
SECRETS_YML
end
end
end
end
# ...
end
You can of course extend this code to add other secrets (e.g. third party API keys, etc.) to be read off of your environment variable:
...
<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
third_party_api_key: <%= ENV["THIRD_PARTY_API"] %>
This way, you can access this secret in a very standard way:
Rails.application.secrets.third_party_api_key
Before redeploying your app, be sure to set your environment variable first:
Then add your modified buildpack (or you're more than welcome to link to mine) to your Heroku app (see Heroku's documentation) and redeploy your app.
The buildpack will automatically create your config/secrets.yml from your environment variable as part of the dyno build process every time you git push to Heroku.
EDIT: Heroku's own documentation suggests creating config/secrets.yml to read from the environment variable but this implies you should check this file into source control. In my case, this doesn't work well since I have hardcoded secrets for development and testing environments that I'd rather not check in.
You can export the secret keys to as environment variables on the ~/.bashrc or ~/.bash_profile of your server:
export SECRET_KEY_BASE = "YOUR_SECRET_KEY"
And then, you can source your .bashrc or .bash_profile:
source ~/.bashrc
source ~/.bash_profile
Never commit your secrets.yml
For rails6, I was facing the same problem as I was missing the following files. Once I added them the issue was resolved:
1. config/master.key
2. config/credentials.yml.enc
Make sure you have these files!
What I did :
On my production server, I create a config file (confthin.yml) for Thin (I'm using it) and add the following information :
environment: production
user: www-data
group: www-data
SECRET_KEY_BASE: mysecretkeyproduction
I then launch the app with
thin start -C /whereeveristhefieonprod/configthin.yml
Work like a charm and then no need to have the secret key on version control
Hope it could help, but I'm sure the same thing could be done with Unicorn and others.
I have a patch that I've used in a Rails 4.1 app to let me continue using the legacy key generator (and hence backwards session compatibility with Rails 3), by allowing the secret_key_base to be blank.
Rails::Application.class_eval do
# the key_generator will then use ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
fail "I'm sorry, Dave, there's no :validate_secret_key_config!" unless instance_method(:validate_secret_key_config!)
def validate_secret_key_config! #:nodoc:
config.secret_token = secrets.secret_token
if config.secret_token.blank?
raise "Missing `secret_token` for '#{Rails.env}' environment, set this value in `config/secrets.yml`"
end
end
end
I've since reformatted the patch are submitted it to Rails as a Pull Request
I've created config/initializers/secret_key.rb file and I wrote only following line of code:
Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]
But I think that solution posted by #Erik Trautman is more elegant ;)
Edit:
Oh, and finally I found this advice on Heroku: https://devcenter.heroku.com/changelog-items/426 :)
Enjoy!
this is works good https://gist.github.com/pablosalgadom/4d75f30517edc6230a67
for root user should edit
$ /etc/profile
but if you non root should put the generate code in the following
$ ~/.bash_profile
$ ~/.bash_login
$ ~/.profile
On Nginx/Passenger/Ruby (2.4)/Rails (5.1.1) nothing else worked except:
passenger_env_var in /etc/nginx/sites-available/default in the server block.
Source: https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_env_var
Demi Magus answer worked for me until Rails 5.
On Apache2/Passenger/Ruby (2.4)/Rails (5.1.6), I had to put
export SECRET_KEY_BASE=GENERATED_CODE
from Demi Magus answer in /etc/apache2/envvars, cause /etc/profile seems to be ignored.
Source: https://www.phusionpassenger.com/library/indepth/environment_variables.html#apache
In my case, the problem was that config/master.key was not in version control, and I had created the project on a different computer.
The default .gitignore that Rails creates excludes this file. Since it's impossible to deploy without having this file, it needs to be in version control, in order to be able to deploy from any team member's computer.
Solution: remove the config/master.key line from .gitignore, commit the file from the computer where the project was created, and now you can git pull on the other computer and deploy from it.
People are saying not to commit some of these files to version control, without offering an alternative solution. As long as you're not working on an open source project, I see no reason not to commit everything that's required to run the project, including credentials.
I had the same problem after I used the .gitignore file from https://github.com/github/gitignore/blob/master/Rails.gitignore
Everything worked out fine after I commented the following lines in the .gitignore file.
config/initializers/secret_token.rb
config/secrets.yml

Set a Rails environment variable locally (Mac OS X)

I'm trying to set environment variables in Rails. I'm following these docs: http://railsapps.github.io/rails-environment-variables.html
One option it gives is to save environment variables in your ~/.bashrc, using this syntax:
export GMAIL_USERNAME="myname#gmail.com"
I tried adding exactly this to my ~/.bashrc. Then I stop my rails server, close my terminal, open my terminal, start rails server. The environment variable still doesn't seem to be available.
I've checked if it is available by doing rails console in my project root folder, and trying > ENV["GMAIL_USERNAME"] # => outputs nil
How can I set an environment variable locally (in development) so that my Rails project has access to it?
I dont know which shell you are using. In case of bash , you can write this in your ~/.bashrc file
export GMAIL_USERNAME=abc#bah.com
then do this in terminal
source ~/.bashrc
Now, check it console . I am sure it will be there .
Create a new file: config/initializers/settings.rb
GMAIL_USERNAME = case Rails.env
when 'development' then 'myname#gmail.com'
end
Restart your app and console.
You should be able to access it wherever you want:
> GMAIL_USERNAME
=> 'myname#gmail.com'

Resources