Mastodonをメンテナンス状態に切り替える方法

標準

Mastodonのインスタンスをメンテナンス状態に切り替えずに停止していたりすると、404(Not Found)だとか502(Bad Gateway)だとかが周りのインスタンスに返してしまうことになり、結果としてPuSH購読を切られてしまう事になります。そうすると一時的にでも(PuSHの更新が7日周期なので最長7日)連合タイムラインが寂しいことになったりと、インスタンス利用者にも迷惑をかけてしまう事になりかねません。

というわけで今後の為にもしっかりと503(Service Unavailable)を返すように設定しながら、メンテナンスが安心して出来るようにNGINXを設定しましょう。

NGINXの設定ファイル

NGINXの設定ファイル(*.conf)は基本的に /etc/nginx/conf.d に全部入っています。この中に拡張子.confのファイルを入れていくことで色々と設定できます。ココらへんの詳しい仕様は適当にググってみるとよく分かると思います。

私のインスタンスでは、公式ドキュメントにもある設定例を基本的に引用してNGINXの設定をしました。今回は、この公式ドキュメント通りの設定でNGINXを動かしていることを前提に説明していきます。

以下のようにMastodonの設定ファイルを書き換えます。

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name haruhi-mstdn.club; #ドメイン名
  # Useful for Let's Encrypt
  location /.well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name haruhi-mstdn.club; #ドメイン名

  ssl_protocols TLSv1.2;
  ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  #必要なファイルが存在するパスを指定
  ssl_certificate     /etc/letsencrypt/live/haruhi-mstdn.club/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/haruhi-mstdn.club/privkey.pem;
  ssl_dhparam         /etc/ssl/certs/dhparam.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  #パスを指定
  root /root/mastodon/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location ~ ^/(assets|system/media_attachments/files|system/accounts/avatars) {
    add_header Cache-Control "public, max-age=31536000, immutable";
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_intercept_errors on;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 504 /50x.html; #500,501,502,504はそのまま
  error_page 503 @maintenance; #503は新たに定義する
  location @maintenance {
    root /var/www/error_pages; #表示させたいhtmlファイルが存在するパスを指定
    rewrite ^(.*)$ /custom_503.html break; #表示させたいhtmlファイルにリダイレクト
    internal; #表面上はリダイレクトしたように見せない
  }

  #ここからメンテナンス状態するかどうかの判定
  set $maintenance false;

  #/var/tmp/503というファイルが存在すればメンテナンスモードに切り替え
  if (-e /var/tmp/503) {
    set $maintenance true;
  }

  #自分はいつも通りにアクセスできるように
  if ($remote_addr = "***.***.***.***") {
  set $maintenance false;
  }

  #メンテナンスモードになっているなら503を返す
  if ($maintenance = true) {
    return 503;
  }
  #ここまで判定
}

一部カスタムが必要な部分がありますが、基本的にはこの通りに書けばちゃんと動くと思います。書き換えた後には nginx -t を実行し、反映させる時は systemctl restart nginx をお忘れなきよう。

表示させるHTMLファイル

デフォルトの503ページでも機能を果たしていれば別に問題は無いのですが、やはりアクセスしてくれた利用者には「いつまで続くのか」「何をしているのか」を明示したいものです。というわけで、専用の503ページを作っていきます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>メンテナンス中</title>
    <meta charset="UTF-8" />
    <style>
      article#main {
      width:80%;
      margin:0 auto;
    }
    </style>
  </head>
  <body>
    <article id="main">
      <h1>メンテナンス中</h1>
      <h2>503 - Service Unavailable</h2>
      現在、Mastodonのアップデートに伴う臨時メンテナンスを行っております。ご不便をおかけしますが、ご理解とご協力の程をよろしくお願いいたします。
      <ul>
        <li>期間:XX時XX分~XX時XX分(予定)</li>
        <li>内容:Mastodon 1.x.x -> 1.x.xへのアップデート</li>
      </ul>
    </article>
  </body>
</html>

これを先程のNGINXで設定したディレクトリに入れます。ファイル自身やディレクトリに対してchmodを使ってパーミッションを変更することを絶対に忘れないで下さいね。そうしないと、せっかくファイルを作っても外部からアクセスすることが出来ません。

メンテナンスモードに切り替え

いよいよ実際にメンテナンスモードに切り替えていきます。今回の設定では /var/tmp/503 が存在するか否かで判定をしていますので、touch /var/tmp/503 を実行するだけで切り替えられます。超便利!逆にメンテナンスモードを解除する時は rm -f /var/tmp/503 を実行するだけです。


tor(外部IP)で確認してみると、しっかりと専用503ページが表示されていることが分かります。しかもURLもそのまま。

この切替さえ忘れなければPuSH購読を切られること無く安心してメンテナンスを行うことが出来るので、是非活用してみてください。

何か不具合などが有りましたらお気軽にコメント下さい。よろしくお願いします。