secrets.yml environment variable not working in Rails 4.1.4 - ruby-on-rails

I am in the process of deploying a Rails app.
I get errors missing secret_key_base in the nginx log file when I have secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> in the secrets.yml file.
I have generated the secret using rake secret in the console and placed in ~/.bashrc as
export SECRET_KEY_BASE="secret"
From the console I run echo $SECRET_KEY_BASE and copy secret to secrets.yml replacing <%= ENV["SECRET_KEY_BASE"] %> with secret.
Then everything works fine and the application runs fine in production environment.
I would rather not keep secret in secret.yml and I do not know how to correct this or what I am doing wrong.
Does anyone have any suggestions?

If you use passenger, add
passenger_set_cgi_param SECRET_KEY_BASE "yoursecret";
to your nginx configuration in the relevant section.
See this section in the passenger user guide.

In production ~/.bashrc might not be read - e.g., you run as a different user, nginx might not read ~/.bashrc before starting, etc. Lots of people run into this issue.
A common approach to this is to handle environment configuration like Rails handles database configuration. Create a config/something.yml file with settings for each environment, then read that yaml in a config/initializers/something.rb initializer and use the values for the specific environment. The rails_config and figaro gems automate this approach. I've often just done it without a gem, as it's not terribly difficult. The key, as with database.yml, is that you never want to check this into source control - use .gitignore with git.
If you want to stick with setting your secret key base using an environment variable, then how you do that depends on your production machine, and how you provision it and deploy your code. With Heroku, it's simple enough to just pop into the Heroku console and set it. For other situations, you could use something like Chef/Puppet/Ansible to set the environment variable for your server. Another approach would be to push that information using Capistrano.

You can put the secret base in /config/initializes/secret_token.rb:
SampleApp::Application.config.secret_key_base = 'Your_Base_here'
EDIT:
This is kind of discouraged in many cases, so edit your .env file and set your key base:
SECRET_KEY_BASE=Your_base_here
and put your secrets.yml back to:
<%= ENV["SECRET_KEY_BASE"] %>
You could alternatively use /config/initializes/secret_token.rb:
SampleApp::Application.config.secret_token = ENV['SECRET_TOKEN']
Which will give you the same result, being more secure.
If you are then planning on pushing this to Heroku:
heroku config:set SECRET_KEY_BASE=$SECRET_KEY_BASE

Related

Missing `secret_key_base` for 'production' environment on Ubuntu 18.04 server (Rails 6.0), multiple topics tried

This topic has a SOLUTION embeded at the end.
PROBLEM
I'm deploying for the first time a Rails app on a VPS on Ubuntu 18.04. with Nginx.
I followed the good tutorial of Gorails "Deploy Ruby on Rails To Production in 2019".
Everything worked, until I had the "Incomplete response received from application" page.
I checked the nginx logs on /var/log/nginx/error.logand saw the typical message "Missing secret_key_base for 'production' environment, set this string with rails credentials:edit"
As the method of Gorails didn't seems to work (after a bundle exec rails secret on his console app-side, he add a file /my_website/.rbenv-vars with a SECRET_KEY_BASE line, filled with the generated secret key), I decided to follow the multiples topics answering to this question.
Here is the thing, I'm not sure if the followings steps are the goods one.
I run bundle exec rails secreton my console, server-side, as deploy user. So I have my GENERATED_KEY_1
I add to ~/.bashrc : export SECRET_KEY_BASE="GENERATED_KEY_1"
I source ~/.bashrc
I check my key with echo $SECRET_KEY_BASE, and I have the good key displayed (GENERATED_KEY_1)
I edited my credential file as
development:
secret_key_base: ORIGINAL_KEY
test:
secret_key_base: ORIGINAL_KEY
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
and added Dotenv to my Gemfile, required it in application.rb
But none of this worked, after restarted nginx server.
So I restarted the previous step, with the root-user.
But again, it failed.
My questions are:
what I am missing ?
How can I know, if it's searching the key in the good place, as I have always the same error message ?
Which key am I suppose to generate ? App-side ? Server-side ? As root or deploy user ?
Do I have something else to configure in /etc/nginx/sites-available/default ? (I saw on this topic that this guys changed a rails_env production; to rails_env development; but I haven't any rails line)
Thank you, I'm a little bit desperate ^^
SOLUTION
During my many tests, I logged with the root user, and run EDITOR="vim" rails credentials:edit. This command had generated a master.key, which doesn't exist on your Github repo.
But first, I didn't modified it. I think that was the main problem, as the application use it to decrypt your credentials.yml.enc file. When I understood it, I edited the master.key with the content of the master.key on my computer app.
Even after editing credentials.yml.encwith <%= ENV["SECRET_KEY_BASE"] %>, this solution works. This corresponds to the answer of Lyzard Kyng, even if it's a bit different.
I can't run EDITOR="vim" rails credentials:editwith the deploy user, it doesn't work.
Rails 5.2 and later uses encrypted credentials for storing sensitive app's information, which includes secret_key_base by default. These credentials are encrypted with the key stored in master.key file. Git repository, generated by default Rails application setup, includes credentials.yml.enc but ignores master.key. After the deployment, which usually involves git push, Rails production environment should be augmented with this key some way.
So you have two options. You can securely upload master.key to production host via scp or sftp. Or you can establish shell environment variable RAILS_MASTER_KEY within the context of a user that runs rails server process. The former option is preferred, but as you have dotenv-rails gem installed, you'd create .env.production file under app's root and put there a line
RAILS_MASTER_KEY="your_master-key_content"
Don't forget to ensure that gem dotenv-rails isn't restricted within Gemfile by development and test Rails environments.
By the way since passenger module ver. 5.0.0 you can set shell environment variables right from nginx.conf
run rake secret in your local machine and this will generate a key for you
make config/secrets.yml file
add the generated secret key here
production:
secret_key_base: asdja1234sdbjah1234sdbjhasdbj1234ahds…
and redeploy the application after commiting
i had the same issue and resolved by this method.
It would be more secure to generate your key on the server and use it there, rather than push it to your repo from a local machine.
Instead of ~/.bashrc do this for using environment variables;
As root user, navigate to the # directory (can probably just use cd ..)
Enter nano home/<yourAppUser>/.bash_profile to navigate to (and create) the file to store the ENV
As you have already, just write this in the file: export SECRET_KEY_BASE="GENERATED_KEY_1"
You can store your database password here as well.
1_ Set credentials with
rails credentials:edit
2_ Upload master.key file to your production server.
If deploy with capistrano, copy master.key to shared folder (shared_path) and then add this to deploy.rb:
namespace :config do
task :symlink do
on roles(:app) do
execute :ln, "-s #{shared_path}/master.key #{release_path}/config/master.key"
end
end
end
after 'deploy:symlink:shared', 'config:symlink'
In my case, on rails credentials:edit, the file indentation were not accurate which gave the error on deployment. So make sure the indentation is correct on your local before deploying.

Separate secret_key_base in Rails 5.2?

I just upgraded from 5.1 to 5.2 and I'm quite confused about this 'better' methodology to storing secrets...
Maybe I'm not understanding, but it seems like now development and production have been 'merged' into a SINGLE SECRET_KEY_BASE as well as master.key... is this correct?
If not, how do I use a separate master key and SECRET_KEY_BASE in development?
What if I have developers helping me and I don't want them to know my master key (or secrets) I use in production?
Rails 5.2 changed this quite a bit. For development and test enivoronments, the secret_key_base is generated automatically, so you can just remove it from secrets.yml or wherever you have it set.
As for production, there is the credentials file which you can generate and edit it by running rails credentials:edit. This will also create the master key in config/master.key which is only used for encrypting and decrypting this file. Add this to gitignore so it's not shared with anyone else, which should take care of sharing it with fellow devs.
If all of this sounds a bit tedious, and it is, you can just ignore it and provide the secret_key_base in ENV. Rails will check if it's present in ENV["SECRET_KEY_BASE"] before it complains.
There are two ways to access secret_key_base:
Rails.application.credentials.secret_key_base
Rails.application.secrets.secret_key_base
Rails 5 took the first way by default.
you can change Rails.application.credentials.secret_key_base by rails credentials:edit. for all other environments, remember to set environment variable RAILS_MASTER_KEY to be the same content of config/master.key. the master.key is git ignored by default. this way uses the same secret key for all environments. if you want to use different keys, you need to control namespaces by yourself.
If you prefer the second way Rails.application.secrets.secret_key_base. you need to create config/secrets.yml:
development:
secret_key_base: ...
test:
secret_key_base: ...
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
remember to set environment variable SECRET_KEY_BASE on production.
if config/secrets.yml file is secret enough, changing <%= ENV["SECRET_KEY_BASE"] %> to plain text is fine.
rake secret can generate a random secret key for you.
I prefer the second way(old way), because of simple.
I used this gem when I didn't want to share the production master.key with my friend developers which I think is the exact same purpose as the OP.
https://github.com/sinsoku/rails-env-credentials
You can have a master key for each evironment as below, so you can have a discretion as to which key you want to share with which developers/deployers.
config/credentials-development.yml.enc
config/credentials-test.yml.enc
config/credentials.yml.enc
master-development.key
master-test.key
master.key
Each key will be generated when you first run something like:
rails env_credentials:edit -e development
If you switch from one master.key setup to this, one error you might encounter will be related to config/database.yml in which Rails tries to evaluate all environment information no matter which environment you are on.
(Even if you comment them out, Rails still tries to evaluate the erb parts.)

clevercloud rails deployment. How to configure env variables?

I'm trying to deploy my rails app in clever cloud. I have deploy several times on heroku, but clever cloud keeps failing my deployment.
I check the log file and fund this:
application.rb:534:in `validate_secret_key_config!': Missing `secret_token` and `secret_key_base` for 'production' environment, set these values in `config/secrets.yml` (RuntimeError)
I've been reading about this problem and it seems to be generated in the .gitignore file, beacuse it ignores the secrets.yml file. The thing is that I have my code in a private repository, so I don't care. I have not secrets.yml in the .gitignore file, but clever cloud keeps complaining about that.
I install the CLI provided by clever cloud and run clever ENV and it returns this:
POSTGRESQL_ADDON_PORT= ####
POSTGRESQL_ADDON_HOST=######
POSTGRESQL_ADDON_DB= ###############
POSTGRESQL_ADDON_PASSWORD=#############
POSTGRESQL_ADDON_USER=##############
I also try to put
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
in my config/environments/production.rb
But I have no results. So, any help?? Thank you!!
(keep in mind that I have not acces to system bash)
If you use the ENV["SECRET_KEY_BASE"] environment variable, you need to set it in your application, via the "Environment variables" tab of your application's details in the Clever Cloud console, or by using clever env set SECRET_KEY_BASE "<the secret stuff>".
If the secrets.yml is not in your .gitignore file, make sure you commited it.

getting error on production related to config.yml

I am trying to push a app on heroku, Its gets pushed but none of my assets gets uploaded on heroku.
Its works all good locally. So I check with rails s -e --production and It gives me error in secrets.yml
It says
Missing secret_token and secret_key_base for '--production' environment, set these values in config/secrets.yml
I am not sure what It is. Please help..
I believe that for a heroku app to run in production Rails expects the secret configuration to exist. Remove the line within your .gitignore that prevents secrets.yml from updating within version control and then make sure you use ENV variables for your secret tokens. If you don't have any secret tokens that aren't just tests then you shouldn't have to worry about it, but if you do you can use gems like figaro to configure your Environment variables that will keep your tokens off VCM.
Edit: If you look within your config directory you should see a secrets.yml that was generated with your app. Within the app you should see your secret_key_base variables within dev, test, and production. Within production though you should have:
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> <- This being your Environment variable

Missing production secret_key_base in rails

I have recently deployed an app and got an internal server error because of missing production secret_key_base. After hours of testing, I managed to solve this problem with two methods:
Method 1:
I generated a new secret_key with rake secret and replaced it with <%= ENV["SECRET_KEY_BASE"] %> in secrets.yml. Deployed the app again and this time it worked. But I think that this method is wrong.
Method 2:
I generated a new secret_key with rake secret and added it to environments/production.rb like config.secret_key_base = 'd1f4810e662acf46a33960e3aa5bd0************************, without changing secrets.yml (default is production: <%= ENV["SECRET_KEY_BASE"] %>). Deployed the app again and it works fine.
My questions:
Which method is the best?
If the 2nd method is correct, why rails does not generate a secret_key_base in production.rb by default?
Is there any other method to do that?
For local development
Generate a secret using rails secret
Method #1: Store this secret in your .bashrc or .zshrc
see https://apple.stackexchange.com/questions/356441/how-to-add-permanent-environment-variable-in-zsh for
Method #2: Use the dotenv Gem
Once you have this gem installed, you then create a .env file in the root of your Rails app that does NOT get checked-into the source control.
https://github.com/bkeepers/dotenv
Method #3 (if using rhc Openshift client)
rhc set-env SECRET_KEY_BASE=3dc8b0885b3043c0e38aa2e1dc64******************** -a myapp
For the server
Method #1: Heroku
Option 1: Store the SECRET_KEY_BASE directly onto the environment
heroku config:set SECRET_KEY_BASE=xxxx
Option 2: Store the secret encrypted with the app and use the master.key file to decrypt it.
Method #2:
For AWS, use AWS Secret Manager to store the master key.
Method #3: For RHC Openshift
connect to your server via SSH and run env so you should see your SECRET_KEY_BASE in the list.
Now restart you app rhc app-stop myapp and rhc app-start myapp
If you're on a normal Ubuntu machine just put export SECRET_KEY_BASE=" <<< output from rake secret here >>> " in your ~/.bashrc.
Run source ~/.bashrc and restart the app.
There is another option that should be a little more secure and that is to add it to the Apache/Nginx configuration file. I'm using Apache and have just used:
SetEnv SECRET_KEY_BASE my_secret
Then just leave the secrets.yml file set to:
production: <%= ENV["SECRET_KEY_BASE"] %>
For a production web server I'm not sure it's valid to assume that a .bashrc file is run and will get your ENV variable set, but I think this way is certain to set it. I'm not and expert so ready to have any risks or reasons why it's not a good idea pointed out to me.
Method 1 is correct. You don't want to store your secrets in the code.

Resources