I have recently asked a similar question to this but as the problem has moved on slighty I have decided to create a new question - I hope this is the expected approach?
Having pushed my Rails 4 app to Heroku I keep getting an Internal Server Error Page and the error is:
You must set config.secret_key_base in your app's config
This is happening because my .gitignore file includes the config/initializers/secret_token.rb deliberately.
I have installed the Figaro gem so that I could set my secret_key_base as an environment variable for added security. I have checked on Heroku that the key has been set correctly.
My code for the secret_token.rb is as follows:
MyApp::Application.config.secret_key_base = ENV["SECRET_KEY_BASE"]
However, I'm still getting the same issue.
Can anyone help???
I did something simlilar to you that worked, but didn't use Figaro. I based it off this blog post
In summary, here's what I did:
1) remove config/initializers/secret_token.rb from your .gitignore
2) Use this code for your secret_token.rb:
MyApp::Application.config.secret_token = if Rails.env.development? or Rails.env.test?
('x' * 30) # meets minimum requirement of 30 chars long
else
ENV['SECRET_TOKEN']
end
3) commit and re-push
4) set Heroku env variale like:
heroku config:set SECRET_TOKEN=12345.....
Worked as soon as Heroku restarted after the config set.
You can set environment variables on heroku:
https://devcenter.heroku.com/articles/config-vars
You need to set SECRET_KEY_BASE environment variable for heroku with this command:
heroku config:set SECRET_KEY_BASE=value
This may help folks using Rails +4.1:
"When deploying a Rails 4.1+ app, Heroku will specify a SECRET_KEY_BASE on
your app by default." (https://blog.heroku.com/container_ready_rails_5)
In other words you won't have to do anything. You can omit secrets.yml (the standard version that is) from your .gitignore file without fear of losing any production related secrets.
Related
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.
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.
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
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
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