Rails

環境変数を用いて手間なく Rails をメンテナンスモード (HTTP 503) に切り替える

サイトメンテナンス時には HTTP 503 Service Unavailable を返すようにするのが SEO の観点から好ましいです。

設定を行う箇所として、ロードバランサ、Rails アプリ、Web サーバなど色々な選択肢が考えられますが、今回は「環境変数のみを用いて設定変更を可能にする方法」を説明します。

背景

「新機能デプロイ時、メンテナンスモードに切り替えたいんだけど、そんな手間のかかることはしたくなくて、社内の IP から以外は全部 503 返したいだけなんだよなー。あと、アプリエンジニアだけで完結させたいなー」

メリット

システム構成次第なところもありますが、環境変数 の変更はロードバランサ、Rails アプリ、Web サーバの設定変更に比べ、非常に手間が少ないです。
例えば、AWS OpsWorks ではブラウザ上から簡単に環境変数の変更、デプロイによる反映が行なえ、ものの数ステップでメンテナンスモードへの移行が完了します。

また、この機能を実現するために必要な Rails の設定も非常に簡素な点もメリットです。
「そんな大掛かりなことしたくなくて、一定期間 503 が返れば良いんだけど……」というケースに最適だと思います。

デメリット

以下に実現できることとして書きますが、実現方法も切替時の設定方法も非常にシンプルなため、機能自体もシンプルです。
Rails アプリ側でもっと複雑な制御がしたいんだけど……というケースであれば biola/turnout のような gem を利用するのが良いかもしれません。

実現できること

  • 環境変数を用いて以下の設定が可能
    • メンテナンスモードの ON/OFF
    • IP アドレスによるホワイトリストの指定

実現方法

以下の設定を app/controllers/application_controller.rb に追加するだけで完了です。

class ApplicationController < ActionController::Base
  before_action :render_503_except_for_whitelisted_ips, if: :maintenance_mode?

  def maintenance_mode?
    ENV["MAINTENANCE_MODE"] == "true"
  end

  def render_503_except_for_whitelisted_ips
    ips_in_whitelist = (ENV["ALLOWED_IPS"] || "").split(",")
    return if ips_in_whitelist.include?(request.remote_ip)

    render(
      file: Rails.public_path.join("503.html"),
      content_type: "text/html",
      layout: false,
      status: :service_unavailable,
    )
  end
end

また、ここでは public/503.html を読み込むようにしていますので、必要に応じて変更してください。

利用方法

以下の環境変数を設定し、それを反映するだけです。

キー
MAINTENANCE_MODE "true" を設定するとメンテナンスモードへ移行します
ALLOWED_IPS アクセスを許可したい IP アドレスをカンマ区切りで指定します

rails server を使った例だと、以下のようになります。

$ MAINTENANCE_MODE=true ALLOWED_IPS=192.168.145.2,192.168.145.3 bin/rails s -b 0.0.0.0

以上、とっても簡単!

まとめ

環境変数を利用すると楽ちん!

リンク