小規模Mastodonインスタンスを運用するコツ

補足:ドキュメント移行によりリンク変更と、tasksに関しての追記を行いました。

最近は、twitterクローンであり分散型のSNSであるMastodonが勢力を伸ばしてきているところであり、自分もハマりつつあります。

実際に運用してみてわかった、大規模Mastodonインスタンスを運用するコツとしてpixiv.netが運営しているサーバpawoo.netでは、現時点で6万人以上のユーザ数を誇るほどの規模です。

その一方で、サーバ自体はオープンソースのため、誰でも立てることができ、立てたサーバはインスタンスとして他のサーバとつながることが出来ます。

実際に私も2,3日程運用して、おひとりさまで運用しております。その時のコツというレベルでもないですが、
これから構築する人に向けてはまりそうな点などをまとめておきます。

https://mastodon.potproject.net/@potpro

では、大規模に対してここでいう小規模とは何か、というと
・主に使用ユーザは1~100人程度を想定
・気軽に構築するため、公式のDockerを使用して構築
・SSLは無料のもの(Let’s Encrypt)を使用する
・サーバはVPS、月1000円~2000円程度
そして、
・ちょっとくらいのダウンは問題なし、データは出来るだけふっ飛ばさないようにする

とします。

VPSとコストに関して

基本的に小規模で運用している方々を見るに、

さくらVPSの1GB(972円/月)やAmazon EC2(従量課金、無料枠あり)が多いと思います。

私はコスパ重視で、お名前.com VPS メモリ 2GBプラン(1,099円/月、年払い)を使用しています。

メモリ2GBと仮想3コアあれば一人でロードアベレージは通常時0.1以下です。1-10人程度であればメモリ1GB以上の好きなVPSを選べばいいと思います。

自宅で管理したいなら、自宅鯖を構築するのも手ですが、固定IPアドレスの問題や安定稼働(停電で使えなくなるとか)を考えなくてはならないため、

その点ではVPSの方が優れているでしょう。

このレベルでどのくらい運用できるのかはまあやっぱり実際に試してみないとわかりませんが、100ユーザくらいなら多分大丈夫(と思いたい。

この部分に関しては公式ドキュメントのResources-needed.mdが参考になります。まだ3つしか参考がありませんが、多分増えていくと思います。
https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Resources-needed.md

この記事はあくまで小規模が目的のため、ユーザ1000くらいを目指すなら、
脱Docker、PostgreSQLやRedisの別サーバー管理、Sidekiq threadsの増加、nginxのチューニング、ロードバランスなどが必要になってきますので、
その部分は他の誰かが解説してくれることでしょう。

Dockerコンテナの作成と構築

基本的に、公式DocumentのDocker Guideを読んで作成してください。
更新が激しいので、ここでは構築方法は解説しません。
何故なら構築方法が変更され、この記事の情報が古くなる可能性が高いからです。

自分がハマった点は、必ず公開用に立てるのであれば、タグ付きのリリース版を使用してください。
https://github.com/tootsuite/mastodon/releases
単純にgit cloneをしてクローンした最新のmasterブランチはうまく動作しない可能性が高いです。
タグ付きのreleaseブランチは、このようなコマンドでチェックアウトできます。

git clone https://github.com/tootsuite/mastodon.git
cd mastodon
git checkout $(git tag | tail -n 1)

アップデート

アップデートも余計なことはせず、公式ドキュメントのDocker Guide – updatingを見て行ってください。
公式DocumentにあるThings to look out for when upgrading Mastodon(Mastodonをアップデートするときの注意点)に記載されていることも重要なので参考にしましょう。
ミスったらデータ消えたり上手く動かなくなるのでここは慎重に。
https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Production-guide.md#things-to-look-out-for-when-upgrading-mastodon

このアップデート手順通りに行えば、すぐに新しくコンテナが立ち上がることでダウンタイムも数秒で済みますし、
まず失敗することはないと思われます。

しかし、万が一の時を含め、バックアップとデータ永続化は行っておきましょう。

データ永続化

一部のデータをホストOS側にマウントすることで、コンテナを誤って削除してもデータが保持される状態にします。
docker-compose.ymlの最初のコメントアウト部分を外すことで、ホストOS側のディレクトリに保存されます。
左側がホストOSのパスとなっているので、変更すれば好きな部分におけます。

version: '2'
services:

  db:
    restart: always
    image: postgres:alpine
### Uncomment to enable DB persistance
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:alpine
### Uncomment to enable REDIS persistance
    volumes:
      - ./redis:/data
(略)

この作業を忘れたまま本番稼働させてしまった場合は、次で紹介するdocker cpコマンドでバックアップを取り、
バックアップをマウントするディレクトリと同じ場所に置き、アップデートを行ってください。

バックアップ

小規模といえど、データのバックアップは行いたいです。

#データベース
PostgreSQLコンテナ : /var/lib/postgresql/data
#キャッシュデータ
Redisコンテナ : /data
#取得した画像等のデータ
Mastodon-webコンテナ :  /mastodon/public/system
#sidekiqデータ
sidekiqコンテナ :  /mastodon/public/system

この4つが基本的なバックアップ対象のデータです。
一番重要なのはデータベースですが、
現バージョンでは、取得した画像等のデータも一度紛失すると再取得を行ってくれず、
タイムラインに取得済みのアバター画像が何も表示されない悲しい状態に陥ってしまいます。

Dockerの場合、Docker cpコマンドを使用することでDockerコンテナからホストOSにコピーが出来ます。
例として、

docker cp mastodon_db_1:/var/lib/postgresql/data /mastodon_data/postgresql

という形です。
mastodon_dataディレクトリにpostgresqlデータが入っていることが確認できると思います。

その他、構築時に使用した.env.productionファイルも無くした場合は再構築が簡単ではなくなるため、バックアップしておいてください。
無くしてしまった場合は、稼働しているMastodon-webサーバから
docker exec -it mastodon_web_1 env
から取得することは一応可能です。

SSL対応

Mastodonサーバでは、SSLの対応はほぼ必須です。

一応httpでも動作しますが、httpとhttpsは共存できないため、httpsのサーバからリモートフォローすることが出来ない、などの弊害があるようです。

今ではLet’s encryptなどを使用してSSL対応は簡単にできるので、個人でも敷居はかなり下がっていると思います。

公式のProduction Guideでは、nginxをリバースプロキシにして、動作することが推奨されています。
公式のProduction Guideをメインに、SSLの設定は自分の過去の記事あたりにその辺は結構書いているので、よければ参考にしてください。

Centos+nginxでLet’s encrypt(certbot)導入と自動更新まで

証明書は期限が切れると使えなくなり、アクセスしてもエラーが出て正常に使えないため、Let’s Encryptを使う場合は自動更新の設定を行うこともおすすめします。

また、公式ではssl_protocols TLSv1.2;になっているため、ちょっと古いブラウザなどで使用できない可能性もあります。
使うべきではないとされているSSLv3を除いて、広く対応を行いたければ、ssl_protocols TLSv1 TLSv1.1 TLSv1.2;に変更することをお勧めします。

Cronjobs

運用するにつれ、他のインスタンスからデータを持ってきて表示するため、放置しているとデータはどんどん溜まっていきます。
それを解消するため、公式で要らないデータ等を削除できるRakeタスクが用意されています。
※特にmastodon:dailyタスクにはPuSHの購読更新処理が含まれるため、外部インスタンスから自分のトゥートが見えなくなる可能性があります。
自分も更新しなくても大丈夫だと思っていたのですが、mastodon:dailyに関しては必ず1日に1回は動かしてください(多くてもOK)。

https://github.com/tootsuite/mastodon/blob/master/lib/tasks/mastodon.rake

#いらないやつもろもろを消してくれるタスク(日一で動作)
0 3 * * * cd /var/www/mastodon && docker-compose run --rm web rake mastodon:daily
#1週間以上前の画像動画キャッシュを削除(週一で動作)
0 3 * * 1 cd /var/www/mastodon && docker-compose run --rm web rake mastodon:media:remove_remote

自分はこのようにしてcrontabで動作させています。

swapの設定

Mastodonに限らないことですがメモリが少なくなっても賄えるようにswapを設定しましょう。
swapがあれば仮想メモリとして退避することができ、遅くはなりますが少ないメモリでもリソースが確保できます。
Mastodonは1ユーザでもそこそこメモリを食います。最低でも1GB、よくて2GBはほしいところです。

特に上に書いているmastodon:dailyタスクは、動作するだけでかなりのメモリを食います。自分もメモリ不足ギリギリ回避な感じでした。

メモリ1GBの場合は3GB、2GBの場合はswapは2GB確保と合計4GBは確保しておけばととりあえず大丈夫と思います。
(Linuxディストリビューションでコマンドが違ったりします。これはcentos7の参考例です。)

//2GB確保、当然ストレージに2GB空きが無いと作れません
if=/dev/zero of=/swapfile bs=1M count=2048
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

まとめ

Mastodonを個人で運用するメリットとして、
・データを勝手に改ざんされたり削除される心配はない
・逆に自分の好きなようにデータを弄れる
・おひとり様サーバならサーバ負担に悩まされることもない(htmlのレスポンスは100ms以下!)
・SNSを運用してるって、なんかカッコいいじゃん。自分だけの空間にするもよし、鯖管で皆を導くのもよし。

という点があり、自分もかなり満足して使っています。

私は個人的にMastodonで個人鯖を立てる人を応援しております。もっとたくさん増えて、個人鯖連合を作ろう。

Facebook PHP SDK v3.2.3でGraph API のバージョンを変更する

今回はいつもと趣向を変えた、バッドノウハウです。

Facebook PHP SDK v3.2.3は、名前の通りFacebookのGraph APIを叩くためのSDKですが、
2015年1月の時点でdeprecated(非推奨)となっております。2年前です。

非推奨というだけで今までは使用できたのですが、このSDKはGraph APIv2.2を使用しているため、利用期限が過ぎ、完全にこのままでは使えなくなりました。

使用期限:2017年3月25日

https://developers.facebook.com/docs/apps/changelog?locale=ja_JP

なので、現在推奨されているFacebook SDK for PHP (v5)を使用しましょう。

で、本来はそこで終了なのですが、実際はそうもいかない人たちもいるようで・・・
Facebook SDK for PHP (v5)はPHP5.3非対応のため、PHP5.3の場合は、このSDKを使用しているところもあります。
PHPバージョンのシェア率を見ると、PHP5.3以下はまだ 25% も存在するようです。
自分もその被害者のため、完全にバッドノウハウなわけですが、対応方法を書いておきます。

この方法で、最新バージョンのv2.8まで動作しました。しかし、完全に動作するとは思わないほうがいいです。
何時使えなくなるかもわからない綱渡り的な状態であり、応急処置みたいなものなので、早いところPHPのバージョンを上げましょう。

参考:facebook graph api not work from 2.2 to 2.3
http://stackoverflow.com/questions/42994019/facebook-graph-api-not-work-from-2-2-to-2-3

まず、バージョンを変更します。デフォルトではv2.2を使用するようになっていますが、そこを明示的に指定することで、バージョンを指定することが出来ます。
v2.8であれば/v2.8/という風にURLを変更します。v2.3にしたほうが無難だと思います。

facebook-php-sdk/src/base_facebook.php 164行目付近

  public static $DOMAIN_MAP = array(
    'api'         => 'https://api.facebook.com/v2.8/',
    'api_video'   => 'https://api-video.facebook.com/v2.8/',
    'api_read'    => 'https://api-read.facebook.com/v2.8/',
    'graph'       => 'https://graph.facebook.com/v2.8/',
    'graph_video' => 'https://graph-video.facebook.com/v2.8/',
    'www'         => 'https://www.facebook.com/v2.8/',
  );

これだけでは動きません。Graph API v2.3から、アクセストークンを取得した時の振る舞いが変更され、配列からjsonを返すように変更されたためです。
そのため、返ってきたjsonをArrayに変換することで動くようにします。
2箇所同じような部分があるので、そこも同じように変更します。両方変更しないとユーザアクセストークンなどが取得できなかったりします。

facebook-php-sdk/src/base_facebook.php 413行目
facebook-php-sdk/src/base_facebook.php 808行目

    $response_params = array();
    parse_str($access_token_response, $response_params);

この部分を以下のように変更します。

    //$response_params = array();
    $response_params = json_decode($access_token_response, true);

これでとりあえずは指定したGraph APIで動作するようになります(v2.3,v2.8以外未確認です)。
OAuthログイン、/me/、/me/account/、/feed/などは動作確認済みです。

もう一度言いますが、PHP5.4以上の方はFacebook SDK for PHP (v5)を使用しましょう。