I am trying a number of different applications into my rails project. For security reasons, I am storing any sensitive keys as environment variables.
This is easy to do with Heroku but on the local environment side I find my windows environment variables starting to pile up. If I happen to have two projects with facebook authentication now I have to name them uniquely on my computer not to get mixed up with each others, which then means I have to rename them in my rails projects, which then means I need to rename them in Heroku... AH
Is there an easier way of doing this such as a configuration file that is added to gitignore, or is that still not quite safe?
What's the best practice for this?
Rails 4.1 comes with secrets.yml, which is where you would put these. Please see this section of the Rails 4.1 release notes for more info.
Related
I'm working on a Rails application and I am attempting to organize my secret_key_base and related important secrets (Think API keys, database credentials, etc.)
I am trying to find a way to setup something like the following, under /config
/config
credentials.yml.enc
master.key
/config/credentials
development.yml.enc
development.key
production.yml.enc
production.key
test.yml.enc
test.key
First Question:
Is it that secret_key_base exists in /config/credentials.yml.enc, which is loaded (first?) and then the credentials are loaded for the environment rails is running in? Or should I create a different secret_key_base for each environment?
Second Question:
No matter what I do, when I run in development or test, tmp/development_secret loads first. In addition, whenever I try to access my secrets in development, (Rails.application.secret_key_base) as referenced here: What's the correct way of defining secret_key_base on Rails 6, I run into an issue where I only ever receive nil when looking for secrets I've defined in my development.yml.enc, which I assume is because it's not loading anything in that file, it's going to tmp/development_secret and not finding anything else (Maybe I'm wrong.)
Goals:
Stop tmp/development_secret from being created, and instead access
secrets using the specific .yml.enc file depending on the
environment.
Understand why /config/credentials.yml.enc exists if it doesn't
load in all the environments. If it doesn't, then it isn't clear when it loads.
Why?
Using config/database.yml as an example, I want to store different creds for each environment, but none of them in version control. (I want nobody but a few to have production.) However, I want to access them the exact same way in all of my environments. Not having creds load in production because of an issue with a .yml file will crash my app, so I don't want to load them differently in test/development.
Put together a blog post about this because searching for documentation on this feature is painful. It's a really easy thing because then only the master.key, and production.key would need loaded as ENV variables which is great. (Or possibility just one of them.)
This really should be a simple, out-of-the-box thing, but it's hard to find real documentation on best practices.
I've found the answer, at least the one I'm looking for. You can have your initializer load whatever file you want by overriding the defaults.
config.credentials.content_path = 'config/credentials/development.yml.enc'
config.credentials.key_path = 'config/credentials/development.key'
https://edgeapi.rubyonrails.org/classes/Rails/Application.html
Can someone explain to me what the Rails environments are and what they do? I have tried researching myself, but could not find anything. From what I gather, the environments are:
Development
Productions
Test
Each "environment" is really just a config. You can launch your app in various different modes, and the modes are called "environments" because they affect the app's behaviour in lots of different ways. Ultimately, though, they are just configs.
BTW you can't have looked very hard when you looked "everywhere", because i just googled "rails environment" and the top result was this
http://guides.rubyonrails.org/configuring.html
which is the official explanation of configuring the rails environment.
From what you have provided in your question, it seems that you are asking:
"What are the difference between each environment configuration in Rails?"
Rails comes packages with 3 types of environments. Each have its own server, database, and configuration. See Rails Guides: Configuration for more information on options available to you.
Setting up the environment
To set your Rails environment, you will want to enter in command line:
export RAILS_ENV=<env>
Where <env> can be test, development, or production. Setting this environment variable is crucial, as it will determine what gems are installed, or what env is touched when running rails console or rails server.
Included in configuration is the gemset used for the app. When you run rails new, you will find a Gemfile with groups test, development, and production. These groups correspond to the environment currently set. When the environment is set to one of those, running bundle install installs all gems related to that group (and gems not listed in a group).
Included environments
test is designed for running tests/specs. This database will likely be bare bones, except for seeds you may call before running the suite. After each test is complete, the database will rollback to its state before the test began. I do not recommend launching rails server, as running tests (via MiniTest or RSpec) will do this for you, and close the server once the suite is finished.
development allows you to "test" your app with a larger database, typically a clone of production. This allows you to test actual real-world data without breaking production (the version that customers or end-users will experience). To view the development environment in action, change the RAILS_ENV and launch rails server. This is good for deciding how you want your pages to look (CSS, HTML). It is also good practice to briefly "test" your app yourself, clicking around making sure everything "looks" good and the JavaScript works.
production is reserved for the customer and end-user. Configuration includes the actual domain of the app, which ports to use, and initializers or tasks to run. You do not want to play around with your database, as it may be customer-impacting. Ideally, the app should work as best as it can, since this is considered your "final product."
Here are some good reads about Rails Environments
http://teotti.com/use-of-rails-environments/
and
https://signalvnoise.com/posts/3535-beyond-the-default-rails-environments
good luck !!
For example, secret_token.rb should not be included. Are there others like this? I plan on starting a new Rails 4 app soon, and I'd like to make it completely open source.
You should not include any db/api keys/passwords/tokens, but this is simple - just store them in ENV variables (but remember to specify that in readme).
As for Rails there's no other file that should really be kept secret.
We have a website using Rails 2.3.x, bundler, nginx, passenger and git, and would now like to use the same code to deploy a very similar site. Differences between the two will include:
Locale
Databases
Validations in some cases
Views in some cases
What is the best way to manage these differences while using the same code base?
Some ideas we've had:
Create new Rails environments, such as production-a and production-b and handle differences in the appropriate environment files. One potential problem is that many gems and plugins are hardcoded to look for production or development environments.
Use Passenger to set a global variable or use the domain per request to determine which context to use. The problem with this are rake tasks, cron jobs, etc that would not have access to this state.
Maintain two versions of the config directory. This would be inconvenient maintaining 2 versions of all the config file, many of which would be identical. Also, I'm now sure how to leverage git to do this correctly.
Any ideas, tips, or examples would be greatly appreciated! Question #6753275 is related but seems incomplete.
One solution I have used in a rails 2.3.x project was to convert the entire site to an engine. That actually is pretty easy, create a folder under vendor\plugins\ and move all the app stuff there. You can see an explanation for rails 2.3 here.
If needed you can even move all migrations and stuff there as well, and use a rake task
to run those.
Everything that needs to be overruled can then just be placed in the actual rails project using the engine. So you would have two rails-projects, with their own configuration, locales and some local overrules, and one big shared plugin/engine.
We used git submodules to keep the code in sync over different projects.
In rails 3 this is even easier, since the engine can now just be a gem.
Hope this helps.
I am trying to deploy my first rails app and struggling a bit. My plan is to initially host it on a heroku free account to get a feel for live deployments and do some production testing. Eventually I might move it to a VPS.
I use git and do not use Capistrano at the moment.
Heroku primarily uses git, which is fine, but git manages the entire project state not files. So I have issues managing configuration files that are different from production to development, for example captcha keys in the environment.rb or goolge js api keys.
So what I did was to..
1 - Take the environment specific configuration out of the enviornment.rb and put it in the development.rb and production.rb. Created a branch called dev where I do my development and then merge it with master and push master to the production heroku remote.
This all works ok, but wondering if there is a better way to do it.
The other massive problem is I might have to use different gems in dev and in herouku. For example, I use ThinkingSphinix for search in dev, but Heroku I have to use acts_as_solr, which means my "Article.search call in the controller, will have to be Article.find_by_solr in production. This can become messy very fast.
What's the best way to deal with this kind of situation?
Thanks
For non-sensitive keys such as Google's JS API key etc., I found this RailsCasts episode very helpful.
Just created a config file under config/ and store your development settings in there.
# /config/google.yml
development:
google:
js:
key: 123456
test:
google:
js:
key: 345678
production:
google:
js:
key: 567890
Then create an initializer inside config/initializers/ that will parse the yaml and create an object which can be used without worrying about the current environment.
# /config/initializers/google.rb
GOOGLE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/google.yml")[RAILS_ENV]
The environment variable RAILS_ENV refers to the current environment, so on application startup it picks up the current type, and you can refer to the settings in your code through GOOGLE_CONFIG:
<script type="text/javascript" src="http://www.google.com/jsapi?key=<%= GOOGLE_CONFIG['js']['key'] %>"></script>
For the latter issue, where code itself differs from environment to environment, I believe Capistrano would be a better solution.
For values that you want to keep different between environments, Heroku offers config vars.
As for using one indexing program in production and another in development, that's a bad idea, and will make things way messier than they need to be. Either start using Solr locally, or set up a Thinking Sphinx instance in EC2 yourself, and have your dynos connect to it.
I would suggest that it is very unwise to have different code in development and production.
Your development, test and production environments should be as similar as possible.
In fact, I would go so far as to say the entire point of the different environments is to simply provide an easy system for allowing minor configuration changes between setups. Different databases, different API parameters, different aching options, but the core system MUST be the same.
The the issue you will face is doubling your development effort. You still have to write the code. So in the search example you provide above, you will have to develop and test twice - once for the Solr production system and once for you local Sphinx, then you need to be able to switch and test between the two approaches in all of your environments to ensure test coverage and functionality.