On handling staging servers

Rails is well known for having good conventions and defaults. So it comes pre-configured with 3 common environments: development, test and production.

But I think that having a staging environment is also pretty common and a good default and I'd ask you to also include this environment by default.

Also, I'd like to suggest a change in the production.rb template:

# See everything in the log (default is :info)
# config.log_level = :debug

This shouldn't be commented. Here is the reason:

find . -name '*.rb' | xargs grep Rails.env.production | grep log

./railties/lib/rails/application/configuration.rb: @log_level ||= Rails.env.production? ? :info : :debug

So, if you decide to copy your production.rb settings to staging.rb you'll have a surprise when you see different logs.

Does it make sense?

The best way to set up a staging server is for it to be configured as close to production as possible, so I always run my staging server using the production.rb environment. If there are differences (like which S3 bucket to use), I put them in ENV settings or in files that aren’t under version control. So I think having a staging.rb file is the wrong way to go.

I also always have a demo environment that is meant for feature acceptance, which is a different role than staging and often has different configuration. I think this is very common for projects that use agile where the PM does story acceptance. But I don’t expect that to become standard in Rails. I think development, testing, and production are really the only ubiquitous environments I’ve seen, and are exactly the right set for Rails to include as standard.

That way you'd need an extra backup (aside from your git repository) for storing each environment data, unless you're using something like Capistrano or Chef. But setting up such environments when you're starting your application may seem like overkill.

Rodrigo.

Also, unless your Chef recipes or Capistrano files are under version control, you'd lose the environment setting changes over the time in case you'd need to understand how it was configured in certain date.

Storing server configuration in your app’s git repo is not ideal. Chef recipes are much better. And if you’re at the point where you need a staging server, you’re definitely at the point where you should be using automation for managing your servers. How else will you know that your staging server accurately reflects the production configuration? You can go a long time without a staging server - often much longer than you can without configuration automation.

And yes, you should store those recipes in version control. Just not in the app’s repo. There are tons of reasons for keeping those things separate (security, decoupling, etc.)

I totally agree with what Josh said. When I used staging rails environment in the past it always ended up with some weird tweaks that I had to do. If you’re running staging server on production environment all you need to do is to remember to keep configuration outside the code as Josh mentioned, which is a good idea anyway.

Or you can just symlink staging.rb to production.rb. But I would never
risk a mistake coming from fact that the entry in my database.yml for
staging would be called production.

Robert Pankowecki

Hi Robert, that is exactly what I’m currently doing, but I was also
afraid about the default “production” environment in passenger
settings, so I renamed my production environment to prod.

That is why I wrote this thread in the first place to note that the

log_level option should not be commented in the production.rb
template file because it will default to ‘info’ only if your
environment is called ‘production’.

Also, I did symlink prod.rb to qa.rb.

I read that keeping the settings in a separate recipe is a better

idea but what I didn’t see are the reasons why is that. Why would it
increase security for example?

Also, adding a staging server is much easier than setting up a Chef

recipe, and I already know Chef:

https://github.com/rosenfeld/gitorious-cookbooks

And I've been using the manual procedure for handling my production

and staging environment for years without trouble, so I don’t think
that automatic management is a must. I’m not saying it is not
useful, indeed it is great to have such feature, but it is just not
that much required. If you don’t feel the need, why bothering about
it?

Cheers,

Rodrigo.

My experience includes having to whitelabel my whole application, putting it under a new domain name, with a small subset of configuration options changing for each deployment. This has led to me having environments for client acceptance, staging, along for each whitelabel. Managing all these configurations cannot be done manually, nor does it make sense (to me anyway) for this to be in some other repo since all the application servers can handle traffic for all whitelabels.

From this I have created a config/environments/_base.rb that gets included at the top of all non-development environment files then additional configuration below. Thusly:

load Rails.root.join(‘config’, ‘environments’, ‘_base.rb’)

YourApp::Application.configure do

environment specific config

end

This has made my configurations much more DRY with each environment now only requiring 3 or 4 lines of specific config, like staging having debug level logging :smiley:

I haven’t thought about how to make this more “standardized” but perhaps with such a pattern it makes it easier to bake-in how one scales out to the next stage(s) of formality with acceptance and staging before live release.

DHH once said the major advancement that Rails provided was empty folders, just a standard place to put things. Any app I go to, I can immediately find the assets, models, etc. In the same vein, I would support shipping with a staging environment. In my ideal world there would be a way to inherit production settings into my staging env, where I could just over-ride them as needed (with a different DB by default).

I was introduced to the concepts of test/develop/prod environments as I was learning Rails. I think that was a good thing. Now that i’m teaching Rails, I make sure to introduce students to the concept since it is so useful. I agree that we can go overboard by providing a million default environments out of the gate and that would be bad. Though most good Rails applications i’ve seen have had a staging environment and server set up, and I believe that vanilla Rails should promote good practices.

I also agree that configuration shouldn’t be stored in source at all, and for those in the thread asking why that is, I think 12factor covers it fairly well http://www.12factor.net/config . I personally like to keep any of my server access tokens, secrets, and connection strings in environment variables, but there are still elements that I set inside of the config files. It would be killer to move Rails towards a source-control-less configuration setup. Even then, I would support having some support for a staging environment out of the gate.

Getting outside of implementation, what are the downsides from users/maintainers to having this functionality in rails new ?

I'm not sure if including a copy of the production.rb file is particularly informative - I'd say the reason for the three we have at present is to offer an example of various categories of environment, each of which requires a particular clump of settings.

The log_level issue does seem relevant, though - maybe the conditional could be inverted to "not development or test"?

--Matt Jones

I'd just prefer that log_level was present (uncommented) in all environments by default, being 'debug' in test and development and 'info' on production.

I disagree that Rails should come with a staging environment by default, even that for the past year I have had staging environments for all my applications as a default when they’re not in Heroku. In that case, I tend to use environment variables to define different settings for both production and staging, but load them both as being in a production environment.

One catch Rodrigo mentioned is the log level for production being hardcode for a ‘production’ environment. I see a benefit for most developers who just copy production.rb to staging.rb having an :info log level being explicitly set on production.rb by default.

I’ve created a pull request for explicitly setting the log_level to
:info in production environment unless someone objects:

https://github.com/rails/rails/pull/5863