mastodon サーバを v3.3.3 から v4.1.4 までバージョンアップする (Non-Docker)


# これは何？
mastodon v3.3.3 から v4.1.4 まで段階的に更新した際の作業メモ。
なお、自分は [ConoHa の Mastodon アプリケーションイメージ](https://www.conoha.jp/guide/mastodon.php)を使っている。このイメージでは Docker を使用していない。そのため、本記事を読む人は注意が必要。

※ mastodon v2.6 系からのアップデートに挑戦したいという場合は[過去に書いた記事](https://qiita.com/g_fukurowl/items/43c500e57c82578f3a8b
)が参考になるかもしれない

# 更新に際してどのような段階を踏んだか
今回の段階的更新を行ったバージョンの組み合わせを表にまとめる。下記の表の、上から順に環境を実現していった。あくまで自分が実現した環境の組み合わせを並べたものであって、mastodon 公式の要求環境の組み合わせ表ではないので要注意。

|mastodon|Ubuntu|Ruby|Node|備考|
|:--|:--|:--|:--|:--|
|3.3.3|16.04 LTS|2.7.2 (apt)|10系|今回の作業前の状態。rbenvは未導入|
|3.3.3|16.04 LTS|2.7.2 (rbenv)|10系|rbenvを導入した。古いrubyは削除|
|3.3.3|18.04 LTS|2.7.2 (rbenv)|10系|Ubuntuを18系へアップグレードした|
|3.4.0|18.04 LTS|3.0.6 (rbenv)|16系||
|3.4.6|18.04 LTS|3.0.6 (rbenv)|16系|mastodon v3.5.0 へ一息に更新しようとも思ったがリリースノートのUpdate stepsでは3.4.6からの更新が前提とされていたので、3.4.6を経由することにした|
|3.5.0|18.04 LTS|3.0.6 (rbenv)|16系||
|3.5.2|18.04 LTS|3.0.6 (rbenv)|16系|[特殊なマイグレーション手順あり](https://github.com/mastodon/mastodon/releases/tag/v3.5.2)|
|3.5.3|18.04 LTS|3.0.6 (rbenv)|16系| mastodon v4.0.0 への更新手順は v3.5.3 からの更新が前提のため |
|4.0.0|18.04 LTS|3.0.6 (rbenv)|16系| [mastodon v3.5.3 からの更新後にerror 500 が返ったので対処が必要だった。](https://qiita.com/drafts/1a91b79e4b43f902e6d6/edit#%E5%A4%B1%E6%95%97mastodon-v400-%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89-error-500-%E3%81%8C%E8%BF%94%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F) |
|4.0.2|18.04 LTS|3.0.6 (rbenv)|16系| [mastodon v4.0.0 からの更新後に error 500 が返ったので対処が必要だった。](https://qiita.com/drafts/1a91b79e4b43f902e6d6/edit#%E5%A4%B1%E6%95%97mastodon-v402-%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89-error-500-%E3%81%8C%E8%BF%94%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F)|
|4.1.0|18.04 LTS|3.0.6 (rbenv)|16系|  |
|4.1.4|20.04 LTS|3.0.6 (rbenv)|16系| [mastodon v4.1.3 時点でリバースプロキシの推奨設定が変わったので nginx の設定ファイル各種を更新したら nginx を起動できなくなった。](https://qiita.com/drafts/1a91b79e4b43f902e6d6/edit#%E5%A4%B1%E6%95%97nginx-%E3%81%8Cduplicate-upstream-%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%A7%E8%B5%B7%E5%8B%95%E5%A4%B1%E6%95%97%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F)また、[ImageMagicの要求バージョンが変わった関係で画像が表示できなくなる問題が発生した。](https://qiita.com/drafts/1a91b79e4b43f902e6d6/edit#%E5%A4%B1%E6%95%97mastodon-v414-%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89%E7%94%BB%E5%83%8F%E3%82%92%E6%8A%95%E7%A8%BF%E8%A1%A8%E7%A4%BA%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F) |

## アップデートに際してやったこと
### バックアップ
自分の環境ではConoHaのVPSを使っている。自分の契約しているプランではバックアップ用にサーバイメージを50GBまで保存可能なので、まずはこれに収まる形にしなければならない。余計なデータを下記コマンドで削除しておく。 [Kumasan Morino さんの記事](https://zenn.dev/kumasun/articles/12dcc7b3e91722945228)を参考にさせていただいた。

**古いプレビューカードを削除**
``` shell
$ RAILS_ENV=production bundle exec bin/tootctl media remove --days=1
```

**どこからも参照されていないメディアを削除**
``` shell
$ RAILS_ENV=production bundle exec bin/tootctl media remove-orphans
```

**古いプレビューカードを削除**
``` shell
$ RAILS_ENV=production bundle exec bin/tootctl preview_cards remove --days=1
```

**[要注意] リモートユーザに関する情報のキャッシュを削除する**
これでもまだ足りない場合、 `/home/mastodon/live/public/system/cache` 以下を消すことを検討しても良いのかもしれない。これはリモートユーザに関する情報のキャッシュらしい。mastodon の GitHub リポジトリにおける [discussion/21287](https://github.com/mastodon/mastodon/discussions/21287) にて、これを削除することの影響についての言及がなされている。もしやるときは自己責任で。

**ConoHaダッシュボードでイメージ保存を実行**
以上のようなことを実施して `df -h` コマンドを実行し、ディスク使用領域が 50 GB に収まっているなら [ConoHa のダッシュボード](https://manage.conoha.jp/Dashboard/)でイメージ保存を実行する。このとき、イメージサイズが制限に収まらなかった場合は "qota error" のような名前の 0 Byte のイメージが保存されるかもしれない。この場合の対処方法については[天満さんの記事](https://kimoota.net/conoha_quota_error/)と [CloudRemix さんの記事](https://qiita.com/CloudRemix/items/5c6c285af11bea36a270)が参考になるかもしれない。

### 環境のセットアップ
環境のセットアップについてはmastodonの[公式ドキュメント](https://docs.joinmastodon.org/admin/install/)を参照した。この公式ドキュメントに記述されている方法で各種環境をインストールまたはアップデートしていった。以下、自分の環境でハマったところだけメモを残しておく。

#### Ubuntu を 20.04 相当に更新
上記公式ドキュメンを見ると、Ubuntu 20.04 が必要とのことだった。アップデート以前の自分の環境ではもっと古いものが入っていたので、まずは Ubuntu の更新から行った。具体的な方法はGoogle検索したら事例がいくつか出てきたので、それらに倣った。自分は[ hitobb 氏の記事](https://qiita.com/hitobb/items/2ee9b1c2c49760976e0f)を参考にさせていただいた。

#### rbenv で Ruby 3.0.6 を導入
公式ドキュメントのやり方に従って3.0.6とbundleをインストールしたが、その後のアセットプリコンパイルのときに古いbundleを見に行くようでエラーが起きた。/usr/local/bin と /usr/bin の bundle を見に行っていたので、`rm -rf` で両方とも削除した。~~また、`visudo` コマンドで ~/rbenv/shims 以下を見に行くようにパスを追加することで何とかした。~~ (mastodon の公式ドキュメントにしたがって環境変数PATHを設定しておけばこれは不要だった)。

実際に Ruby 3.0.6 が必要とされるのは mastodon v4.1.2 からなので要注意。

## アップデートに際して失敗したこと

### 失敗：rbenv への移行で散々ハマった
公式ドキュメントによれば rbenv が推されているようだったので、自分の環境にもこれを導入することとした。従来の自分の環境では Ruby2.7 をapt-getでインストールしていた。そこで、まずは `apt-get remove ruby2.7` のようにして既存環境を削除した。
~~次に、公式ドキュメントの方法でrbenvを導入することを試みたがうまくいかなかった。もっと簡単な方法はないかと検索したところ、[apt-get で rbenv を導入している事例](https://zenn.dev/nukokoi/articles/e03fe2372b43a7)を見つけたので自分もこれに倣った。~~
apt-getでrbenvをインストールすると古いgemがインストールされた関係で、その後の手順に支障がでた。
結局、素直に公式ドキュメントのやり方に従ったら何とかなった。

しかしその後、各種mastodonサービスの起動がうまくいかず頭を悩ませることになった。主な原因は[後述](https://qiita.com/drafts/1a91b79e4b43f902e6d6/edit#%E5%A4%B1%E6%95%97systemd%E3%81%A7mastodon%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E3%81%A8bundle%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F)するが、この原因に至るまでに `bundle exec rails` で ruby2.7コマンド が見つからないのでわざわざ `alias ruby2.7=ruby` してなんとか対処したりした。他にもいろいろよくわからないことが起きたが、/home/mastodon/live/vendor/bundle 以下を削除して再度 `bundle install` したりこまごまとした対応を行った。

### 失敗：ユーザー "mastodon" を削除したら既存の mastodon 関連ファイルが全部消えた
諸々の作業中、いろいろ試行錯誤する過程でユーザ名 "mastodon" を削除した。その結果、ローカルのmastodonリポジトリの内容もビルド結果もDBも何もかも消えてしまった。ユーザ "mastodon" のホームディレクトリ以下がすべて削除される形になった。

本メンテナンス作業を行う前日にサーバイメージのバックアップは取っていたので、ConoHaの管理者ダッシュボードからサーバ再構築を実行した。一部の新しいトゥート等のデータは失われたが、従来の機能を復旧することには成功した。

### 失敗：ユーザー "mastodon" を使わずにメンテナンス作業をしていた
今までユーザー "mastodon" としてメンテナンス作業をすることを一切やっていなかった。

[公式ドキュメント](https://docs.joinmastodon.org/admin/install/#setting-up-mastodon)を見ると、ruby とか bundle の環境をセットアップして使うのは "mastodon" だった。実際、 GitHub から mastodon のリポジトリを取得してこれに関する環境のセットアップやビルドを行うのは多くの場合 "mastodon" として行うことがドキュメントには明記されていた。

また、各種 mastodon サービス (mastodon-web, mastodon-sidekiq, mastodon-streaming) の .service ファイルにはこれらが "mastodon" として実行されることが記述されていた。自分はいままでそういう認識の無いまま、なんとなくメンテナンスをして、なんとなくうまくいってしまっていた。今回、 ユーザ "mastodon" のアカウントを誤って削除したことでそのことに気づくきっかけとなった。

今まで mastodon 以外のユーザとしてメンテナンス作業を積み重ねてきたせいか、 mastodon ユーザであれば本来実行可能な操作が不可能になっていたので、root ユーザとして /home/mastodon 以下のアクセス権限を mastodon に対して改めて付与した。具体的には `chown -R mastodon /home/mastodon/live` コマンドを実行した。

#### 追記(2024-02-06)
`su - mastodon`でユーザをmastodonに切り替えたら`exec bash`すべし。もちろん ~/.bashrc に必要な設定を書き込んだ状態で。
詳細は[公式ドキュメント](https://docs.joinmastodon.org/admin/install/#setting-up-mastodon)を参照。

### 失敗：systemdでmastodonのサービスを起動するとbundleコマンドが見つからずエラーになった
systemdはユーザが設定した環境変数を勝手に読み取ってくれるわけではないらしい。[参考にさせていただいた記事](https://qiita.com/FPC_COMMUNITY/items/1f6711732a3db1a4817c
)に従って、/etc/systemd/system/multi-user.target.wants 以下の mastodon-web.service, mastodon-sidekiq.service, mastodon-streaming.service ファイルに `EnvironmentFile=/etc/sysconfig/mastodon` を追加した。

ここで追加した /etc/sysconfig/mastodon は参考記事を元に作成した。mastodon としてログインしたときの環境変数 PATH の内容をほぼコピぺして PATH を各種 mastodon サービスに反映するもの。

### 失敗：期待しないバージョンのRubyが使われる
rbenvに移行して`rbenv global 3.0.6`のようにしたが、/home/live/mastodon 以下で `bundle install` を呼び出したところ、なぜか Ruby v2.7 向けに /home/live/mastodon/vendor/bundler 以下に依存パッケージがインストールされている様子が見て取れた。このとき live 以下に展開されていた mastodon のソースは v3.3.3 相当で、 live/.ruby-version には Ruby 2.7 系のバージョン番号が明記されていた。このため、期待しない Ruby バージョンに関する環境が導入されていた。.ruby-version を編集し、3.0.6 に変更したことで、期待するバージョンの Ruby が使われるようになった。

### 失敗：Ruby 3.0 系でデフォルト搭載でなくなったライブラリがあった
各種環境のアップデートの過程で、mastodon v3.3.3 を RUby 3.0.6 環境で動作させようとするタイミングがあった (これは自分のアップデートのやり方が特殊なだけで、本来は mastodon v3.3.3 を Ruby 3.0 系で動作させる必要はない)。このとき、 rails コマンドを呼び出そうとすると rexml というライブラリが見つからない旨のエラーメッセージが出力された。[StackOverflow の関連スレッド](https://stackoverflow.com/questions/65479863/rails-6-1-ruby-3-0-0-tests-error-as-they-cannot-load-rexml)によれば、この gem がデフォルトで使えたのは Ruby 2.7 までとのことだった。スレッドで案内されているように Gemfile を編集して rexml を導入する旨を追記し、解決できた。

### 失敗：Ruby 3.0.6 に上げるのが早すぎた
Ruby 3.0.6 を要求するのは mastodon v4.1.2 からにも関わらず、早くバージョンを上げすぎた。mastodon v3.3.3 時点では Ruby 2.7.2 を使うのがデフォㇽトだが、Ruby バージョンを早くに進めすぎたため、余計な失敗をしてしまった。せめて Ruby 3 系を始めて要求するようになる mastodon v3.5.0 から Ruby 3.0.6 を使うようにしていたら、もっと時間を節約できたかもしれない。

### 失敗：mastodon v4.0.0 にアップデートしたら error 500 が返るようになった
v3.5.3 から v4.0.0 への更新後、ブラウザから自鯖にアクセスすると error 500 が返るようになってしまった。しかし手元のiPhoneにインストールされているクライアントアプリからアクセスすると問題なくTLが見れた。mastodon-*.service 各種のステータスを確認したが、それぞれアクティブな状態であることが示されていた。調べてみると、同様の症状がmastodon公式の[issue](https://github.com/mastodon/mastodon/issues/20727)
として報告されていた。報告にあったように、`RAILS_ENV=production bundle exec rails assets:clobber` でアセットを削除してから再度 assets:precompile したところ、問題が解消された。

### 失敗：mastodon v4.0.2 にアップデートしたら error 500 が返るようになった
v4.0.0 から v4.0.2 への更新後、ブラウザから自鯖にアクセスすると error 500 が返るようになってしまった。手元のiPhoneにインストールされているクライアントアプリからはアクセスできないが、mastodon-*.service 各種のステータスを確認するとそれぞれアクティブな状態であることが示されていた。同様の症状がmastodon公式の[issue](https://github.com/mastodon/mastodon/issues/20727)
内でも報告されていた。自分の場合は `RAILS_ENV=production bundle exec rails db:migrate` を実行して各種 mastodon-*.service を再起動したところ、問題が解消された。

### 失敗：nginx が　"duplicate upstream" エラーで起動失敗するようになった
mastodon v4.1.4 に更新する際、プロキシサーバーの推奨設定が変わった旨が Upgrade notes に記載されていたので、nginx の設定ファイルを更新したところ見出しの問題が起きた。[公式ドキュメント](https://docs.joinmastodon.org/admin/install/#setting-up-nginx)に nginx のセットアップ手順が記載されていたのでこれにならったが、`systemctl reload nginx` に失敗してしまった。 

`systemctl status nginx` で状態を確認したところ、'"duplicate upstream "backend"' というエラーが出ていることが確認できた。

[teratail で似たような問題に関する質問](https://teratail.com/questions/123426)を調べたところ、重複する upstream "backend" が存在するということらしいことがわかった。

 nginx がほかに include している設定ファイルを確認したところ、余計なファイルまで読み込んでいた。/etc/nginx/nginx.conf を編集し、 /etc/nginx/sites-enabled/mastodon を明確に読み込むように変更したところ、問題が解消された。

### 失敗：mastodon v4.1.4 にアップデートしたら画像を投稿・表示できなくなった

mastodon v4.1.4 にアップデート後、TL上の画像投稿トゥートの表示がおかしくなった。どの画像もサムネイルが壊れていた。また、サムネイルをクリックしても正しい画像が表示されることはなかった。また、自分の手元でpngなどの画像ファイルを投稿しようとした際には、"500 Error processing thumbnail for uploaded media" のようなエラーが表示されて失敗した。

[mastodon v4.1.4 の Upgrade notes](https://github.com/mastodon/mastodon/releases/tag/v4.1.4)を確認したところ、以下の記述があった。

> If your uploaded images are broken after the upgrade, it means your installed ImageMagick version is older than the new minimum version (6.9.7-7), for example if you are running Ubuntu 18.04. If this happens, you can find more informations and ways to fix it on this page.

しかし自分の環境は Ubuntu 18.04 LTS と ImageMagick 6.9.7 以上がインストールされていた。もう少し調べてみたところ、下記２つの Issue を見つけた。

- [Broken images after 4.1.3 / 4.0.5 / 3.5.9 upgrade #25776](https://github.com/mastodon/mastodon/issues/25776)
- [Regression: Image previews broke with 4.1.3 upgrade when using ImageMagick older than 6.9.7-7 #25769](https://github.com/mastodon/mastodon/issues/25769)

後者のスレッドで renchap 氏が示すのと同じ手順で ImageMagick-7.1.1 を入れ直したところ解決した。

renchap 氏の示すように `apt-get install build-essential pkg-config checkinstall libx11-dev libxext-dev zlib1g-dev libpng-dev libfreetype6-dev libxml2-dev libjpeg62-dev libwebp-dev` を先に実行しなければならない。もしこれを無視して ImageMagcik の更新だけを行うと、Delegate にメディアの拡張子が含まれないので要注意。

また、古い ImageMagic をアンインストールしても policy.yml が残り続ける可能性もあるので気を付けたい。それがトラブルの原因になるかは不明だが、念のため /etc/ImageMagic* を確認した方が良い。

なお、これは余談だが、自分の場合は renchap 氏の情報にたどり着くまでに Paperclip ライブラリの挙動自体を疑って迷走してしまった。 "500 Error processing thumbnail for uploaded media" で検索して[ヒットした情報](https://github.com/mastodon/mastodon/issues/21330)に基づいて mastodon-web.service のプロセスのログを確認し、 /home/mastodon/app/controllers/api/v2/media_controller.rb を編集し、問題発生個所の詳細を辿ったところ Paperclip というライブラリで問題が発生していることを特定した。


[Paperclip は ImageMagic と連携して画像のサムネイルを作成したりするのに便利なライブラリらしい](https://beck23.hatenablog.com/entry/2014/10/26/234330)。しかしオリジナルの [Paperclip](https://github.com/thoughtbot/paperclip) は既に Deprecated となっている。 mastodon では [kt-paperclip](https://github.com/kreeti/kt-paperclip) というまだアクティブなフォークを使用している。実際、最新の Gemfile を確認すると kt-paperclip の名前を見つけることができた。しかし何も考えず `bundle install` したところ、自分の環境には古い paperclip と kt-paperclip の両方がインストールされた状態になってしまった。


一度 /home/mastodon/vendor/bundler/ruby/3.0.0 を `rm -rf` で完全に削除してから `bundle install` すると kt-paperclip だけがインストールされた状態を実現できた。これが今回の問題の直接の原因だったわけではないが、調査時の混乱を招くノイズにはなっていた。


# アップデートに際してやってよかったこと
### 段階的な環境更新を行った
当然といえば当然なのだが、複数のソフトウェアの組み合わせから成る環境全体を一息に大きくアップデートするのは危うい。何か問題が発生したとき、どの変更が起因しているのかわからない。古い mastodon を一気に更新しようとするのではなく、段階的にバージョンアップ作業を繰り返すのがやはり安全だと判断した。

また、今回は mastodon の更新だけでなく rbenv への移行や Ubuntu のアップグレードも行おうとしたため、いろいろとハマってしまった (今までの怠惰の負債が地雷になっていた部分も多々あった)。そのため例えば 「まずは mastodon 自体の更新を一切行わず、rbenv の導入だけを試みる。rbenv 環境に移行したら現在運用中の mastodon サービスを再起動して、正常動作することを確かめる。不正動作するようなら原因を調べて対処する。正常動作したらサーバイメージのバックアップを都度取っておく」というようなステップを随所で踏んだ。時間はかかるが、結果的には遠回りが近道になったと思う。**関係するソフトウェアを１つでも更新するということは、サービスの状態を何かしら変更することに等しいと思う。** 何かを更新したらそれがきっかけで不正な動作が発火するかもしれない。石橋を叩きながら渡るのが大事だと学んだ。

### 記録を取りながら作業を行った
それから、これは割といままでもやってきていたつもりだが、作業中に行き当たった問題やその対処等をリアルタイムに記録しておくのは大事だった。都度都度詳細なレポートを書くわけではなく、メモ帳にちょっとした疑問や「こうしたらいいのかも」のような思い付きを書き残したり、試したこととその結果を走り書きしておけば良い。メモを取ることすら面倒な場合は、重要な情報が表示されているときのターミナルのスクリーンショットや写真を撮っておいて、ファイル名としてコメントを書いておくと良かった。

### 人に見せるためのドキュメントとして記録を取った
自分の場合はQiita記事の下書きをメモ帳代わりにして、アップデート作業と記事作成作業を同時並列に進めた。走り書きのメモを人に見せるつもりのドキュメントに整形する過程で、作業のまずいところや今後の方針などが明確になっていく感じがあって、自分の場合はやりやすかった。

# 感想
一連のアップデートを開始してから終了するまでに4日かけた。1日あたり5時間程度を費やしたので、20時間かかったことになる。普段から少しずつやっていればこんなことにはならなかったのではないか。

サーバーの保守・運用を日常的に行っている人からすると「当たり前でしょ」と言われるようなことも、素人なりに日曜鯖缶をやっているような自分はサボってしまいがちである。今後はこまめにバージョンアップを追うことにしたい。

systemd についてヒントをくれたもちゃさん(mot@mastodon.motcha.tech)、オライリーの「[入門　モダンLinux](https://www.oreilly.co.jp/books/9784814400218/)」を紹介してくれた Ogino さん(omasanori@mstdn.maud.io) ありがとうございました。