Missing secret_key_base for production environment - hosting a rails 4.1.4 app on heroku - ruby-on-rails

I created a rails 4.1.4 app which I'm trying to host on heroku, but I get the following error - Missing secret_key_base for production environment, set this value in config/secrets.yml My secrets.yml file looks has secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> under production
I ran rake secret and saved the result in the environment variable SECRET_KEY_BASE. When I log into my app on heroku, I can see that value stored in the Config Variables when I click on settings. Other solutions have suggested I add config/secrets.yml to git and redeploy to heroku - however I don't wish to add secrets.yml, or any yml file to version control.
Any ideas?Thanks!

When you deploy to Heroku, you're deploying via Git. Any files that aren't included in your git repository won't be pushed to your server. As a result, it doesn't matter what you have in your secrets.yml right now - it's not being deployed.
There's nothing wrong with committing configuration files or YAML files - the problem is in committing secrets. If you commit your API keys and passwords then you have to trust everyone with access to your source code. That's impossible if your code is on Github (because you don't trust everyone on earth with a computer), but is still a bad idea in a small company. You'll be far less stressed if someone leaves, loses their laptop, or gets infected with malware if they don't have production credentials on their machines.
You're already doing the right thing to avoid this. Using environment variables to configure your app keeps those secrets out of your repository, even if those configuration files are committed.

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.

"Missing `secret_key_base` for 'production' environment" error on Heroku

I received the error "An unhandled lowlevel error occurred" when deploying my app for the first time on Heroku, and heroku logs shows:
Missing secret_key_base for 'production' environment, set this value
in config/secrets.yml
1) The default secrets.yml specifies secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> for production
2) I generated a secret using rails secret, then added this to my app's Heroku config via heroku config:set SECRET_KEY_BASE='(the key)'
3) heroku config shows this value set for SECRET_KEY_BASE
4) Perhaps most importantly, based on older questions regarding this error, .gitignore does not include secrets.yml--it's the default .gitignore generated for a Rails 5 app. Therefore, secrets.yml should have been deployed with my app, which specifies that the secret be loaded via an environment variable in the production environment.
5) I've also run heroku ps:restart, in case the app needed some extra help for the environment variable setting to take effect
I read older posts, but the past answer seemed to be ensuring secrets.yml was not included in .gitignore, but as mentioned, this does not apply to the default Rails 5 .gitignore.
What else can I try? Thx.
Edit: When I set the config value at the command line, I also receive the Heroku message:
Setting SECRET_KEY_BASE and restarting (the app)... done
Okay, I see what happened. Running heroku run bash and checking which files were deployed has been enlightening.
It is true that secrets.yml was not in the .gitignore file for my local repo, but it seems that someone--possibly malicious hackers, possibly gremlins--had added secrets.yml to my global .gitignore (.gitignore_global), and so this file was in fact not being pushed to Heroku.
I've removed the secrets file from my global .gitignore, offloaded the dev and test environment secret keys to dotenv for management, and can run my deployed app successfully.
I thought about deleting the question, but will leave it in case others run into this problem, or even a similar one where using heroku run bash may be helpful when diagnosing issues with apps on Heroku.

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

secrets.yml environment variable not working in Rails 4.1.4

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

How do I open source my Rails' apps without giving away the app's secret keys and credentials

I have a number of Rails apps hosted on GitHub. They are all currently private, and I often will deploy them from their GitHub repository. I'd like to be able to make some of them open source, just like the ones you can find on http://opensourcerails.com.
My question is: How can I make these repositories public without giving away super secret credentials?
For example, I can look in /config/initializers/cookie_verification_secret.rb and see the cookie secret for nearly every one of them. I don't understand how this is acceptable. Are these users all changing these values in their deploy environments somehow?
Some users even expose their AWS secret and key! Others will instead set their AWS secret to something like:
ENV['aws-secret']
although I'm not sure at what point they're setting that value.
So, what are the best practices for open sourcing your Rails app without compromising your app's security.
I recently went through this with one of my own apps. My solution was to store anything secret in a git-ignored YAML config file, and then to access that file using a simple class in the initializers directory. The config file is stored in the 'shared' folder for the Capistrano deployment and copied to config at each deploy.
Config store: http://github.com/tsigo/jugglf/blob/master/config/initializers/juggernaut.rb
Example usage: https://github.com/tsigo/jugglf/blob/6b91baae72fbe4b1f7efa2759bb472541546f7cf/config/initializers/session_store.rb
You may also want to remove from source control all history of the file that used these secret values. Here's a guide for doing this in Git that I used: http://help.github.com/removing-sensitive-data/
If you're using foreman, put an .env file in the root of your app. (foreman docs)
.env will have
AWS_SECRET=xxx
AWS_ACCESS=yyy
Then when you need to use the keys, insert:
ENV['AWS_SECRET']
ENV['AWS_ACCESS']
Though it's important that you don't commit this .env to your version control. So if you're using git, add the .env to your .gitignore.
Bonus round! - Heroku
If deploying to Heroku, these environment variables need to be configured in the Heroku environment, too. There are two options:
Manually add the keys through the heroku config:add command
Use the heroku-config gem to synchronize your local environment variables, both ways.
Not storing any secret value at all. At any point in the history of a Git repo.
Those values should be stored elsewhere, leaving only template config files versioned, along with a script able:
to read the right values from the external repo
and build the final config file complete (with the secret values in it)
By keeping the tow set of data separate (sources on one side, secret values on the other), you can then open source the sources repo without comprising any secrets.
I actually took a hint from your question, using ENV.
I had three different secret values that I didn't want made available. They're the app's secret token of course, and Twitter's consumer key and secret. In my secret token initializer:
KinTwit::Application.config.secret_token = ENV['SECRET_TOKEN']
Twitter.consumer_key = ENV['CONSUMER_KEY']
Twitter.consumer_secret = ENV['CONSUMER_SECRET']
I'm hosting my project on Heroku, so I added these as configuration variables to Heroku.
[03:07:48] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_KEY=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v7
CONSUMER_KEY => ub3rs3cr3tk3y
[03:08:40] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_SECRET=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v8
CONSUMER_SECRET => ub3rs3cr3tk3y
[03:08:57] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add SECRET_TOKEN=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v9
SECRET_TOKEN => ub3rs3cr3tk3y
Now, the values are ready on my next push. But, what if you aren't using Heroku? I'm obviously not an expert on every single rails deployment (jeesh, not even a Heroku pro), but an example of this would be doing a db:migrate for testing.
$ RAILS_ENV=test rake db:migrate
The KEY=value pair before the command sets the environment variable, so running this command, echo ENV['RAILS_ENV'] would print test. So however this is set up in your environment is how you would do it. But, the environment variables aren't in your code, so that's the trick.
[EDIT - The following method has the annoyance of having to switch to the Production branch to run "rails server" in order to include necessary cookies. Thus, making edits while the server is difficult... and I'm still looking for a good solution]
After further investigation, I think the solution I was looking for was to exclude anything that stored a secret value from my Git repo's master branch (just as #VonC said). But instead of then reading from those files in a separate repo, I simply create a new "production" branch and add them to that.
This way they're excluded from Master and I can push that to Github or some other public repo just fine. When I'm ready to deploy, I can checkout the Production branch and merge Master into it and deploy Production.
I need to be able to do this because Heroku and other hosts require a single git repo to be pushed to their servers.
More information here:
http://groups.google.com/group/heroku/browse_thread/thread/d7b1aecb42696568/26d5249204c70574

Resources