Disable dangerous rake tasks in production


Yesterday, we had to restore the production DB from a backup, since we ran "rake db:schema:load" in production by mistake. To avoid that problem in the future, I decided to disable that task, and others than can screw with the DB, in production. 

It was a matter of adding a prerequisite to those dangerous tasks, that checks if they are being run in production, and exit accordingly. I also added a flag to override this safeguard, together with some code to backup the DB. To do this, I added the following code to lib/tasks/disable_db_tasks_on_production.rake:


DISABLED_TASKS = [
  'db:drop',
  'db:migrate:reset',
  'db:schema:load',
  'db:seed',
  # ...
]

namespace :db do
  desc "Disable a task in production environment"
  task :guard_for_production do
    if Rails.env.production?
      if ENV['I_KNOW_THIS_MAY_SCREW_THE_DB'] != "1"
        puts 'This task is disabled in production.'
        puts 'If you really want to run it, call it again with `I_KNOW_THIS_MAY_SCREW_THE_DB=1`'
        exit
      else
        require 'heroku'
        puts 'Making a backup of the database, just in case...'
        puts `heroku pgbackups:capture`
      end
    end
  end
end

DISABLED_TASKS.each do |task|
  Rake::Task[task].enhance ['db:guard_for_production']
end
It would be nice to add something like this to the default Rails app, since, if you are reading this, chances are high that is too late for this to protect you by now :)

Some feedback from reddit's darkphnx, nice to know we're not the only ones :)
Initially you think "What sort of moron would write db:schema:load" on a production machine, but it's not that simple. 
Plenty of application hosting systems will look at what sort of application you're deploying and make assumptions about what commands should be run on first deployment. Very often one of these is "rake db:schema:load".Let's say you're deploying to a new hosting environment, but pointing to an existing database. If you forget to check what commands are going to run on first deployment deployment it will come along and be very helpful "oh, this is the first time you've deployed this app, I'll load the database schema for you". db:schema:load drops any existing tables.If you're not watching the deployment carefully, the first time you'll know is when the deployment is complete all your data is gone. If you're lucky you were watching and you've only lost a couple of tables.Source: Did exactly this, had to restore a 50GB table from backup.

11 comments:

  1. Excellent idea, and I plan to start using it right away.

    You didn't say where to place this code - I'm assuming Rakefile, but it would probably be a good idea to clarify that.


    ReplyDelete
  2. Just clarified it, you need to add it to a new rake task, lib/tasks/disable_db_tasks_on_production.rake for example. Happy you like it!

    ReplyDelete
  3. thanks!!!! make my day!

    ReplyDelete
  4. You shouldn't need to require the heroku gem if you're just going to shell out to the heroku command line app.

    ReplyDelete
    Replies
    1. The heroku plugin is, ironically, not available in heroku, so you need the gem there.

      Delete
  5. useful, thank you! I hope it'll make into rails
    these are the ones I've used:

    DISABLED_TASKS = [
    'db:drop',
    'db:drop:all',
    'db:fixtures:load',
    'db:migrate:reset',
    'db:purge',
    'db:purge:all',
    'db:reset',
    'db:schema:load',
    'db:seed',
    'db:setup'
    'db:structure:load'
    ]

    ReplyDelete
  6. Very very good idea! Why don't you send a patch to rails right now ;)

    ReplyDelete
  7. Thanks friends, for providing such enlightening data.
    mediaonlines.com

    ReplyDelete
  8. You probably know as well as I do that SEO isn’t like Paid Search, where you can bring in leads, at volume, pretty quickly.
    xenforo custom bbcode

    ReplyDelete
  9. Male Sex Toys
    Waooow!!! Magnificent blogs, this is what I wanted to search. Thanks buddy

    ReplyDelete