How to create a new environment in Ruby on Rails? - ruby-on-rails

I'm trying to create a new environment (build) for using it with hudson.
I'm doing this because I didn't want to mix up my test databases with hudson test database.

Assuming you want create the hudson environment.
Create a new environment file in config/environments/hudson.rb. You can start by cloning an existing one, for instance config/environments/test.rb.
Add a new configuration block in config/database.yml for your environment.
Update any other configuration file you might have under the config folder with your new environment, some gems create their own ymls under the config folder.
That's all.
Now you can start the server
rails server -e hudson
or run the console
rails console hudson
And so on.
If you are using an older version of Rails, the commands are
ruby script/server -e hudson
ruby script/console hudson

Updated Answer for Rails 5
Create new environment file:
config/environments/staging.rb
Modify the following files to add the environment key 'staging'
config/cable.yml
config/database.yml
config/secrets.yml
Gemfile (incase you have stage dependent gems)
The new environments can now be used as usual for eg:
rails server -e staging
rails console staging
Or to do conditional checks:
rails console staging, Rails.env.staging?
Good place to start for creating new environment and to modify these files is to copy production settings.

If you're using webpacker in your Rails 5 app, also make sure to update your config/webpacker.yml. If you forget to add your new environment to config/webpacker.yml, it will just fall back to using your production config.

Create a file config/environments/build.rb which will contain the options specific to your environment.
Add your new environment's database credentials in config/database.yml.
Rock and roll!

Related

Rails credentials files and Rails environment

Rails 7
I am running into some issues using [Rails.env.to_sym]. Some config files understand it, and some do not.
Doing some research, it seems as if I can generate different credentials files, for each runtime environment. For instance:
rails credentials:edit --environment development
rails credentials:edit --environment test
Does this mean that Rails will pick the appropriate credentials file, based on the rails environment setting (test, development, etc.)?
That’s correct — the main credentials file (credentials.yml.enc) is overwritten by environment-specific files.
If you run bin/rails credentials:edit -h from the command line, you’ll see this:
=== Environment Specific Credentials
The `credentials` command supports passing an `--environment` option to create an environment specific override. That override will take precedence over the global `config/credentials.yml.enc` file when running in that environment. So:
bin/rails credentials:edit --environment development
will create `config/credentials/development.yml.enc` with the corresponding encryption key in `config/credentials/development.key` if the credentials file doesn't exist.
One tiny gotcha for me — I ran into an error trying to generate environment-specific credentials file (part of error below):
`binwrite': No such file or directory # rb_sysopen - config/credentials/test.yml.enc.tmp
My fix was creating the empty folder first (config/credentials) and then re-running command (e.g., bin/rails credentials:edit --environment test)

Capistrano and API keys in ENV variables?

I'm deploying my rails app with Capistrano. I want to save some API keys on the server as an environment variable. Those API keys should be accessible to my rails app that is deployed with Capistrano. Those API keys should also be accessible to a separate ruby file that is run as a daemon.
setting the API keys in environment variables seems like the ideal solution, however, I can't access them in my rails app with ENV["SOME_KEY"].
According to this post, because capistrano runs as non interactive and non login, ~/.bashrc and ~/.bash_profile are not loaded. The flowchart suggests that I should use $BASH_ENV.
Can I just add my api keys in $BASH_ENV and access them in my rails app and in the ruby file that is a daemon with ENV["SOME_KEY"]?
I'm also thinking of just adding the api keys to a file somewhere on the server and symlinking it to the ruby file dir and rails dir and just open and reading it. Would this be possible?
There are a few ways that work well with Capistrano, in my experience.
rbenv-vars
If you use Ruby via Rbenv on your server, then you are in luck. There is a Rbenv plugin called rbenv-vars that automatically injects environment variables into any Ruby process, which would include your Rails app. Just add your variables to ~/.rbenv/vars on the server using KEY=value syntax. That's it.
dotenv
The dotenv gem is a similar solution, but it works as a gem you add to your Rails app and doesn't require Rbenv or any other supporting tools. Add dotenv-rails to your Gemfile and deploy. Dotenv will automatically look for a .env.production file in the root of your Rails app. For Capistrano, create a .env.production file on the server inside Capistrano's shared directory, and then add .env.production to :linked_files. Now every deploy will link to it. Declare your variables using KEY=value syntax.
.bashrc
Declare your variables with export KEY=value syntax at very top of the ~/.bashrc file on the server. On Ubuntu, this file is evaluated even during an non-interactive SSH session. Just make sure you place the declarations on the top, before this case statement:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
CentOS may be a different story, so YMMV.
I made a Capistrano plugin capistrano-env_config some time ago for managing and syncing environment variables across a Capistrano cluster which works by modifying the /etc/environment file to make environment variables available throughout the system. It's easy to use and is similar to how you can set environment variables with the Heroku toolbelt. Here are some examples:
cap env:list
cap env:get[VARIABLE_NAME, VARIABLE_NAME, ...]
cap env:unset[VARIABLE_NAME, VARIABLE_NAME, ...]
cap env:set[VARIABLE_NAME=VALUE, VARIABLE_NAME=VALUE, ...]
cap env:sync

AWS OpsWorks Environment variables not working

I am running Ubuntu 14.04 LTS 64 bit Rails Application and I am unable to access my App environment variables.
In OpsWorks App panel, I set my environment variables, say:
MYKEY: 1234
Then I save and deploy my app again to make these visible.
In my Rails app, or the rails console I get nil:
$ bundle exec rails c production
>ENV["MYKEY"]
=> nil
I have tried restarting the server. I'm not sure what I am missing, I have been using environment variables in other services.
How can I trace where these should be set?
OpsWorks stores environmental variables in different places depending on what kind of app you're deploying. On Rails / Passenger they should be saved in the Apache config file #{your_app_name}.conf. (Source)
This means they aren't available in your normal shell environment.
I know the Node.js recipes stored everything in an /srv/www/#{app_name}/shared/app.env file... which is then sourced to pull in the environment to run the Node server. This implementation detail also meant you could write shell scripts that sourced that app.env file, then called some Node script or whatever.
Of course, Rails isn't Node. I have no idea if the environmental variables are also stored somewhere else or not: a quick look at the Rails recipes in the OpsWorks cookbooks didn't find anything obvious, but maybe I missed something.
Depending on the amount of modifications you have going on in your OpsWorks cookbook, you could create a deploy recipe that does something like this:
application_environment_file do
user deploy[:user]
group deploy[:group]
path ::File.join(deploy[:deploy_to], "shared")
environment_variables deploy[:environment_variables]
end
(maybe adjusting the path)
Then to run your console, when you're SSHed into the server, do something like
sudo source /srv/www/my_app_name/shared/app.env; bundle exec rails console -e production or whatever.
AWS OpsWorks console lets you declare environment variables but to let them be available for our Rails app we need to use a Chef cookbook recipe plus some precautions.
In a nutshell we use the config/secrets.yml file combined with config/application.yml file, Figaro gem and a Chef cookbook recipe.
The chef cookbook recipe read the variables defined in OpsWorks console and let them available to Rails app writing the config/application.yml file.
I have published a detailed guide to explain how exactly do it. Link here.
These are the core points that I covered:
Use config/secrets.yml file (added from Rails 4.1)
Use Figaro gem to load variables in the environment
Declare environment variables inside AWS OpsWorks Console
Use a custom Chef recipe to create a config/application.yml file that Figaro will use to let variables available
I (with some help from Bruno at the AWS PopUp Loft in NYC) added some custom Chef code inside the after_restart.rb deploy hook, simply add the folder "deploy" to your apps root directory and inside add "after_restart.eb." In it ....
Chef::Log.info("Running deploy/after_restart.rb")
contents = []
node[:deploy].each do |application, deploy|
deploy[:environment_variables].each do |key, value|
contents << "export #{key}=\"'#{value}'\""
end
end
Chef::Log.info("Adding the environment variables to /etc/profile.d/startup_env_config.sh")
bash "create_startup_env_config.sh" do
user "root"
cwd "/etc/profile.d"
code <<-EOH
echo \''#{contents.join(" ")}\'' > startup_env_config.sh
source startup_env_config.sh
cd #{release_path}
EOH
end
And that's it. If you update the environment variables inside the OpsWorks panel remember to restart your instances.

Error message: Unknown database 'someweb_production' (Mysql2::Error)

I'm trying to run this web aplication of Ruby on Rails with Apache using Phusion Passenger. I already configured the httpd.conf file.
I also have another aplication which runs with 'rails server' commmand, and it's connecting to the development database. However, i don't understand why the aplication which runs with apache it's trying to connect to a production database that i didn't create yet instead development as it should be.
What i have to configure to make my Ruby on Rails application run as development?
Apache with Phusion provide a production level web server environment, rails server (WEBrick) is a simple web server that lets you test locally. You typically use one or the other on a given machine. But not always :-)
But to answer your question, which database is used by Rails is determined by the RAILS_ENV variable, which is by default, one of production, development or test.
When you create a new rails application, a default database configuration is created in the file app/config/database.yml -- there are separate sections that provide necessary parameters for connecting to your database(s). Other environment-specific configurations may be specified either in the environment.rb or in app/config/environments/<name>.rb.
In your Passenger config, you can set the RAILS_ENV variable as documented here http://www.modrails.com/documentation/Users%20guide%20Apache.html#rails_env.
I just realized also that it seems like Passenger is looking for production (expecting the db name to be someweb_production) -- chances are you have to run a bundle exec rake db:migrate in the production environment in order to (create and) initialize the database. You may need to pass the environment parameter in this case also.
For your local config (rails server) the server will look for a shell environment variable named RAILS_ENV, and you can also pass a specific environment on the command line e.g. rails server --environment=development. I think if neither is specified, rails server defaults to development.
The problem was that i didn't include the following lines in the Apache conf file:
RailsEnv development
RackEnv development

Managing security for an open source rails 3 application stored at github

New to rails, open source and soon ready for deploying to a production environment, I have some security considerations.
How to handle the database.yml is covered pretty good by, how-to-manage-rails-database-yml
But from my point of view there are more configuration settings in a normal rails application that shouldn't be hosted in a public github repository and deployed to production e.g.
devise.rb -> config.pepper
secret_token.rb -> Application.config.secret_token
capistrano -> deploy.rb
...
Adding config/****/* to .gitignore would not only prevent new developers from bundle install, db:create, db:migrate, rails server but also to keep the production config up to date if a new gem with an initializer is installed.
Another possibility would be add an environment.yml with sensitive config, like database.yml where sensitive configuration in the initializers will be overridden?
This will make it easy to get up and running after a clean checkout and the production environment will be easy to maintain.
Any ideas how to approach my problems above?
I usually put "safe" data in these files, which will usually work for development purposes. But in production I symlink the files to another location with capistrano, like this:
invoke_command "ln -sf #{shared_path}/database.yml #{release_path}/config/database.yml"
So in the production server I have a bunch of files that override the files in source control. I don't even work with a database.yml.example, just some sane default database.yml that the developers agree upon to use in development and test.
For individual settings, like API keys, I usually create a config/settings.yml and read them from inside the initializer:
SETTINGS = YAML.load(IO.read(Rails.root.join("config", "settings.yml")))
YourApp::Application.config.secret_token = SETTINGS["secret_token"]

Resources