[Fediverse][Mastodon] Mastodonサーバの再建:v3.1.3版

しょーがないのでスタンドアロン版で復旧を図る

先の記事でも書いたのですが、Kubernetes基盤に構築していたMastodonが華麗にも吹っ飛びました。
そこで頑張って復旧にいそしみ、5/11にようやく復帰しました。イヤー、非常に長い道のりだった。現在はサービス自体は再開してるんですが、3ヶ月ほどデータが巻き戻ってしまいました。

参考として、あるいは備忘録として記事にまとめることにしました。

前提条件

  • アプリケーションサーバとDB/Redisサーバの2本立て
  • Nginxは既存統合リバースプロキシサーバを使用する
  • アプリケーションサーバは新設、スタンドアロンサーバとして構成する(いわゆる非Docker)
  • OSはCentOS7-Latest
  • CPUは4vCPU、メモリは12GBで構成。
  • データベースサーバは既に構成済み(というか、古いデータを用いて復旧済み)
    • 当時のデータはMastodon 3.0.1ベースのものだった
  • Elasticsearchは今は構成しない
  • コンテンツデータは統べて再構築・再取得する(既存データを元にアタッチすることは考えない)
  • SSL終端は既存統合リバースプロキシにて行うため、アプリケーションサーバではやらない(既に終端の仕組みが出来てる)

Mastodon公式の導入手順はUbuntuベースである上、今時のこのソフトウェアはインストール対話スクリプトが動くように構成されており、再構築には向いてない手順だったので、古の知見が結構役立っていたりする。ただ・・・かなりハマったよ。

再構築手順

Node.jsを導入

Node.jsですが、Version13を入れるとasset:precompileとかYarnを使ったインストール処理で派手に躓くので大人しくVersion12系を導入しましょう。

# curl -sL https://rpm.nodesource.com/setup_12.x | bash -
# yum install -y nodejs

yarnを導入

yarn導入は専用リポジトリを取り込んで導入する感じになります。

# yum install gcc-c++ make
# curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
# yum install yarn

関連リポジトリを導入

PostgreSQL用リポジトリを拾ってきます。

# yum -y localinstall https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

あと、大抵は入れてる人多いと思うんですが、EPELは加えておきましょう。

# yum -y install epel-release

前提パッケージインストール(多分漏れあり)

公式サイトにUbuntu向けに記載されてるパッケージを突合しながら必要なものを並べて見ました。抜け漏れあるかもしれませんのでご注意くださいー。

# yum -y install ImageMagick ImageMagick-devel libxml2-devel libxslt-devel pgdg-libpq5 openssl-devel file-libs protobuf-lite-devel protobuf-lite protobuf-lite-static pkgconfig gcc autoconf bison bison-devel libyaml-devel zlib-devel ghc-zlib-devel ncurses-devel ncurses-libs libffi-devel gdbm-devel gdbm redis postgresql10 postgresql10-contrib libidn-devel libicu-devel jemalloc-devel readline readline-devel kernel-devel kernel-headers

FFMPEGのインストール

サムネイルを作る処理で必要となるアプリケーションです。Nux-desktopと言うリポジトリが必要になります。

# rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
# rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
# yum -y install ffmpeg ffmpeg-devel

その他パッケージのインストール

開発パッケージを導入します。

# yum groupinstall "Development Tools"

PostgreSQLの旧バージョンのライブラリを入手しておきます。
これを入れておかないと、pgというGemをインストールする際にエラーを吐かれてしまいます。

# yum -y install postgresql96-devel
# yum -y install postgresql-devel

アプリケーション実行ユーザの作成、切り替え

アプリケーション実行ユーザを作成し、suコマンドで切り替えます。

# adduser mastodon
# passwd mastodon
# su - mastodon

Ruby環境の構築

以下のようにコマンドを実行してRuby環境を構成していきます。中身は全く理解していませんw。

$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv && src/configure && make -C src
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec bash
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

$ RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.6.6
$ rbenv global 2.6.6

$ gem install bundler --no-document

Mastodonソースの入手

GitHubよりMastodonパッケージのソースファイルを入手し、これをliveディレクトリに放り込みます。
基本、bundleやyarn等各種操作はこのliveディレクトリで全て行うことになります。

$ git clone https://github.com/tootsuite/mastodon.git live && cd live

Mastodonのビルド・インストール

mastodonソースをビルドし、bundleコマンドとyarnコマンドを用いてインストールしていきます。

恐らく以下はPuma(Web)とSidekiqの導入

$ bundle config deployment 'true'
$ bundle config without 'development test'
$ bundle install -j$(getconf _NPROCESSORS_ONLN)

で、こちらは多分Streamingのインストールじゃないかな。

$ yarn install --pure-lockfile --ignore-engines

キーの作成

シークレットトークンを作成しておきます。

$ RAILS_ENV=production bundle exec rake secret
$ RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key

.env.productionに対して各種必要な設定を行います(ここでは詳しく書かない)

$ vi .env.production

パッケージのバージョンに内部データを合わせる

新規インストールの場合は、setupスクリプトを動かすんですが、今回の構成ではデータベースに既存データが存在している状態なので、単純にDBやコンテンツの更新だけを行います。まずはDBの更新。

$ RAILS_ENV=production bundle exec rails db:migrate

そしてコンテンツのビルド

$ RAILS_ENV=production bundle exec rails assets:precompile

サービスの定義

前回はコンテナベースで作成したため、コンテナとしての登録さえ出来れば、後はコンテナのON/OFFをするだけだったんですが、今回はスタンドアロンホストであるためにsystemdで制御できるよう構成しなければなりません。

また、別途Nginxを構えてる場合、公式のサンプルをそのまま使うとサービスの待ち受けIPが問答無用で「127.0.0.1」となり、Nginxから繋がせようとしても悲劇の502が返ってきます。これを回避するために環境変数として「BIND=0.0.0.0」の定義が必要になるので注意してください。

mastodon-sidekiqサービス

デフォルト値からDB_POOL数とsidekiqの引数を変更しています。

# vi /etc/systemd/system/mastodon-sidekiq.services
-----
[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="BIND=0.0.0.0"
Environment="DB_POOL=75"
Environment="MALLOC_ARENA_MAX=2"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 75
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
mastodon-streamingサービス

BIND変数の定義のみ変更しています。

# vi /etc/systemd/system/mastodon-streaming.services
-----
[Unit]
Description=mastodon-streaming
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="NODE_ENV=production"
Environment="BIND=0.0.0.0"
Environment="PORT=4000"
Environment="STREAMING_CLUSTER_NUM=1"
ExecStart=/usr/bin/node ./streaming
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
mastodon-webサービス

Webワーカー数をデフォルト2から6に増やしています。思いのほかリソースを食わないのでがっつり高めに。

# vi /etc/systemd/system/mastodon-web.services
-----
[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="RAILS_SERVE_STATIC_FILES=true"
Environment="BIND=0.0.0.0"
Environment="WEB_CONCURRENCY=6"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
各種サービス起動

更新を反映後、サービスを起動します。最終的には systemctl enable mastodon-* を忘れずに。

# systemctl daemon-reload
# systemctl start mastodon-*

コンテンツ等の更新

この時点で、コンテンツ情報はMastodonサーバを新規設置したときの状態に近く、色々なコンテンツが欠損しています。また、最後に更新したデータが古いために、その間にたたんでしまったMastodonサーバが結構居るかもしれません。なので、以下のコマンドで後始末をして再出発をします。

今はもうなくなってしまったMastodonサーバのデータを消去する

$ RAILS_ENV=production bundle exec bin/tootctl accounts cull --concurrency=20

Mastodonサーバが関係する全てのアカウント情報を再取り込みする(これでコンテンツががっつり拾われる)

$ RAILS_ENV=production bundle exec bin/tootctl accounts refresh --all

後はSidekiqのダッシュボードなどを眺めてみて、殺到してくるJobが無事捌けていればOKっす。サーバがダウンして恐らく3-4日程度はかかってたと思うので、それなりに一気に洪水がやってきましたが、Sidekiqのキューを75にしていたこともあったからか、比較的さっと処理を片付けることが出来ました。

生命線と呼べるシステムをある程度復旧させたので、今また無謀にもIsilon-SD Edgeの再建に走ってるところです。