biola/turnout

Can't get turnout to work on heroku

luisbraga opened this issue · 5 comments

Is anyone else having trouble using turnout on heroku?
I've just created a new app and deployed it but it only works locally.

This is my gemfile

source 'https://rubygems.org'
ruby '2.2.2'

gem 'rails', '4.2.5.1'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'turnout'

group :development, :test do
  gem 'sqlite3'
  gem 'byebug'
end

group :development do
  gem 'web-console', '~> 2.0'
  gem 'spring'
end

group :production do
  gem 'pg'
  gem 'rails_12factor'
end

And here is turnout.rb in config/initializers


Turnout.configure do |config|
  config.app_root = '.'
  config.named_maintenance_file_paths = {default: config.app_root.join('tmp', 'maintenance.yml').to_s}
  config.default_maintenance_page = Turnout::MaintenancePage::HTML
  config.default_reason = "The site is temporarily down for maintenance.\nPlease check back soon."
  config.default_allowed_paths = []
  config.default_response_code = 503
  config.default_retry_after = 7200
end

maintenance.yml is created when running rake maintenance:start and is deleted on maintenance:end
Still not working. Am I missing something?

Thanks in advance.

Hmm, I just pushed up a test app to Heroku and I'm seeing the same thing. It works locally in development but not in production. I'll see if I can dig into it and figure out what's going on.

Okay, so I think I know what's going on here. Turnout works by writing a tmp/maintenance.yml file. Because Heroku starts up a new dyno to run rake tasks it's not writing the file anywhere that the web dyno can find it.

The only way I found to get this to work is to create a web endpoint to start and stop maintenance mode

class MaintenancesController < ApplicationController
  def start
    Turnout::MaintenanceFile.default.write
    render text: 'Maintenance mode on'
  end

  def end
    Turnout::MaintenanceFile.default.delete
    render text: 'Maintenance mode off'
  end
end

Of course if you do this you should authenticate those requests somehow. Also make sure you allow the path to that controller in Turnout config. Otherwise you'll never be able to turn maintenance mode off.

Turnout.configure do |config|
  config.default_allowed_paths = ['/maintenance']
end

It wouldn't be hard to trigger it with an environment variable, but it would require restarting the web server. I've had at least one other person request that there be a Redis backend or similar that could be used to enable and disable maintenance mode. That would require some work, but it's doable.

All that to say, you may just want to stick with Heroku's own maintenance mode.

Thanks for taking your time testing and providing an alternative.
I'll probably stick with Heroku's approach. Too bad there's no option for allowed ips.

ncri commented

Using an env var rather than a temp file is crucial in many environments, not only on Heroku. We use Kubernetes and have the same issue, as multiple pods with their own file system are running our app. Switching maintenance mode on will only work as long as requests go into the server instances that have the file. And also a restart or deploy will exit maintenance mode.

Thanks for the input @ncri. I'd be happy to support an environment variable if it can be integrated in a clean way. I'll go ahead and reopen this issue as a placeholder. I'd certainly be happy to accept a pull request from anybody who wants to accept it. In the mean time, I can't commit to any timeframe, but I'd be happy to add this as a feature myself whenever I am able.