I must not be the only one who occasionally wants to stop a Ruby on Rails application. There are long-running and risky database schema migrations and data migrations, and you don’t want users fiddling the system in the middle of the deployment.
With a Mongrel-based setup it was easy to set up a 503 (Service unavailable) error page and then just shut down all the Mongrels, so that Apache could give users a maintenance page. Using mod_rails (Phusion Passenger), only restart is supported out-of-the-box.
However, it’s possible to use mod_rewrite to prevent users from accessing your site during the deployment. Try this in your Apache virtual host configuration file:
# This option is not needed with Passenger >=2.1.1.
RailsAllowModRewrite on
ErrorDocument 503 /503.html
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}/../tmp/stop.txt -f
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /$1 [R=503,L]
Basically the last three lines mean:
- If there is a tmp/stop.txt file
- and user is requesting a file that does not directly exist in the file system
- then return error 503 and render the appropriate maintenance page
It doesn’t actually stop your Rails processes, though. They will die when Passenger times out.
Now it’s also easy to incorporate this to your Capistrano configuration:
namespace :passenger do
desc "Restart Passenger"
task :restart, :roles => :app do
run "touch #{current_path}/tmp/restart.txt"
end
desc "Stop Passenger"
task :stop, :roles => :app do
run "touch #{current_path}/tmp/stop.txt"
end
desc "Start (or un-stop) Passenger"
task :start, :roles => :app do
run "rm -f #{current_path}/tmp/stop.txt"
end
end
After this it’s safe to deploy big new releases without completely taking down your Apache.
