RACK_ENV: It's not *for* you
Posted: Sun, 13 October 2013 | permalink | 3 Comments
(With apologies to Penny Arcade)
I’m probably the last person on earth to realise this, but the RACK_ENV
environment variable (and the -E
option to rackup
) isn’t intended for
consumption by anything other than Rack itself.
If you want to indicate what sort of environment your application should run
in, you’re going to have to do it via some other means.
Why is this? Because the interpretation that Rack applies to the value of
RACK_ENV
that you set makes no sense whatsoever outside of Rack. Valid
options are “development
”, “deployment
”, and “none
”. If you follow
the usual Rails convention of naming your environments “development
”,
“test
”, and “production
” (and maybe “staging
” if you’re feeling
adventurous), then in any environment other than “development
”, you’re
not going to be telling Rack anything it understands.
As I said, I may be the last person on earth to have worked this out, but I
doubt it. There are plenty of bug reports and “WTF?” blog posts and Stack
Overflow questions that appear to stem from people misunderstanding the
purpose of RACK_ENV. Sadly, the Rack documentation is very quiet on the
whole topic, and the only place that mentions how the environment is
interpreted is in the comments for Rack::Server.new
– and that doesn’t
tie that environment to the -E
option or RACK_ENV
environment
variable.
At any rate, the take away is simple: unless you want Rack to pre-configure
a bundle of middleware for you, RACK_ENV
or rackup -E
is not the
configuration variable you’re looking for. Use something else to tell your
app how it’s supposed to work.
3 Comments
From: Scott Muc
2014-02-12 06:14
Nope, you’re not the last person. It looks like those that have used RACK_ENV to mean a conceptual environment name have just had things work by coincidence.
Thanks for the post. I’m going to make sure that RACK_ENV is one of the valid options in my projects and refer those that disagree to this post. I know Sinatra is guilty of overloading the purpose of this variable.
From: Dennis
2015-01-08 01:10
It seems that in some cases we have little choice when it comes to changing
RACK_ENV
.For example, if you use dotenv-deployment for managing your app’s .env files for different environments, then (unless I’m missing something) you’re forced to change
RACK_ENV
.This is because it determines the environment like this
ruby if environment = ENV['RACK_ENV'] || (defined?(Rails) && Rails.env)
As you can see,
RACK_ENV
takes precedence.If you use Heroku and run
heroku config
, you’ll see that Heroku setsRACK_ENV=production
(it also setsRAILS_ENV=production
).So if you have your staging and production environments on Heroku, and you have your staging and production configuration files (i.e.
config/environments/{staging,production}.rb
), then you’ll need to set the env vars that Heroku uses appropriately – you’ll just have to modify the staging values forRACK_ENV
andRAILS_ENV
since production already has the correct values by default.I hope this doesn’t break anything I’m not aware of fingers crossed. I’m not really sure yet how
RACK_ENV
is used by Rack (and whatever else may be using it), so I’m just treading in the dark right now.From: Matt Palmer
2015-01-08 08:11
Hi Dennis,
Thanks for your comment.
Yes, it does suck rather a lot that various other applications have latched onto
RACK_ENV
and are misusing it. It’s rather the reason why I wrote this post originally (although I didn’t specifically call out framework and library authors, as I probably should have).It seems to me that
dotenv
is definitely doing it wrong (way, way wrong), although Heroku is (probably) doing it right – they should be settingRACK_ENV
(because they’re using Rack compatible appservers). The problem only comes when everyone else usesRACK_ENV
, as well, instead of having their own environment variable. I universally setRACK_ENV
tonone
, because that’s the behaviour I want out of Rack; so very, very many other things freak out. Practically speaking, though, it doesn’t bother me as much as it used to, because I’ve moved from usingdatabase.yml
-style configs-in-files to configuring everything via individual environment variables, because that’s so much more flexible, and doesn’t require hard-coding all sorts of things about the app environment in the codebase.To answer your last question, Rack itself uses
RACK_ENV
primarily for setting a default middleware stack (as per the docs forRack::Server.new
and the related code. The astute reader will note that the docs and the code don’t match, which amuses me too much to be willing to ruin it by submitting a pull request.Post a comment
All comments are held for moderation; markdown formatting accepted.