Calckey 13.1.4.1からFirefish 1.0.3へアップデート

ケチケチインスタンスだと余計なところで引っかかる可能性 / 2023-08-08T00:00:00.000Z

特にこのサイトではお知らせしてはいませんでしたが、2023年7月3日に私はCalckeyの個人インスタンスである「c.osumiakari.jp」を運営しています。Twitterが本当に終わってからだとFediverseの海へ飛び込むのは遅い(…と思いましたが青い鳥はもうどこかに飛び立ってしまっていましたね)と思った上、私のようなカスがどこかのサーバーの負担になってもいけないなあと思い、個人インスタンスを立ててみています。

さて私がインストールを行った際にはCalckeyのバージョンは13.1.4.1でしたが、7月20日に「Firefish」に改名され、色々な機能が追加されつつあります。個人的にはあまり要らない改変も多く、インストールスクリプトやドキュメントの整備が追い付いていない印象もあり当分アップデートはしないつもりでいました。しかしながらリリースノートを丁寧に読んでみると、単にFirefishへアップデートするだけでは、Calckeyのバージョンを上げるのと大して変わらないのではないかと思いやってみることにしました。引っ掛かったところが無かったわけではないので、それも併せて記録していこうかと思います。

結論

  1. リリースノートを見ながらやる
  2. 余計な要素が要らなければ思ったよりシンプル
  3. ケチケチインスタンスだとメモリが足りないかも

Firefish

この記事にたどり着いた方の大半はFirefishがどのようなものかを知っているかと思いますが一応簡単に説明しておこうかと思います。FirefishはMisskeyv12のフォーク( なのにWebサイトでは全部の成果を自分で一から作り出したような見た目になっていない?とは思うし、Misskey開発陣のクレジットは隅に置くのに自分がさらにフォークされたのならばもっとちゃんとクレジットしろ!と言うんですね…という点はある )で、Mastodonとの互換性が向上している他、検索性が高かったりアカウントの引っ越しが行いやすかったりするという嬉しいポイントがあるものです。

当然ながらActivityPubを話すため、先述したMastodonやMisskeyに限らず、AkkomaLemmyPeerTubeといったものが動いているサーバーと(どの程度かは通信先によりますが)相互にコミュニケーションを取ることが出来ます。そのため1つアカウントを持つだけで、様々なサーバーにいる様々なコンテンツに触れ、様々な人間とコミュニケーションを楽しめるというものです。

これを見てアカウントを作りたくなった方はFirefishが動いている公開サーバー一覧からいい感じのインスタンスを選ぶか、分散SNSに気持ちのある謎の知り合いに誘導されながらアカウントを作ると良いでしょう。また懐に余裕がある方は自分でサーバーを立ててみると、極めて教育的効果の高い体験型学習をすることが可能なのでやってみるといいかもしれません。

アップデート

というわけで2023年7月3日の私は極めて教育的効果の高い体験型学習をすることにしたのですが、私の懐は残念ながらそこまで大きくない(ちなみにご支援はここからいい感じにしてくれると嬉しいです)ので、メモリ1GBのケチケチインスタンスを立てることにしました。別にCalckeyの最低要件にはRAMが特に書いていないですし、個人的に小規模インスタンスを運営されている方(Calckeyではありませんが)への伝手があったので、勇気を出して質問してみると「小規模鯖でMastodonじゃなければ2GBあれば余裕だし、800MBくらいあればまあOKじゃない?知らんけど」といったような趣旨の返答をいただきました。

というわけでメモリ1GBの環境を用意したのですが、Calckeyはビルドされたものが転がっておりそれを適当に設置するのではなく、当然ですが自分の環境でビルドするものです。そのためビルドをする必要があるのですが、ビルドにはある程度のRAMが必要であることが知られています。私は思考のプロなので伝家の宝刀†スワップファイル†を用いることでこの問題を力業で解決しました。

思考のプロらしく腕力で解決しそれなりに安定した運用を行っていましたが、建立から1週間ほど経ったある日、Calckeyは将来的に改名するよ!といったノートが流れてきました。ものすごく重要な情報なのにCalckey公式アカウントではなく開発者の個人アカウントで情報を流すのは、イーロン・マスクの悪い面を感じてあまりいい気持ちにはなりませんでしたが、それはそうとしてアップデートの煩雑化の可能性について考えていました。

CalckeyにはMisskey由来の「ubuntu-bash-install」といったスクリプトが用意されていました。これをwgetでいい感じに持ってくると対話をするだけでインストールが終わるという優れもので、アップデート用のスクリプトまで用意されていました。一般にソフトウェアのアップデートは戦いの始まりを示す法螺貝が吹かれるようなものなので、自分でやりたくないものランキングの上位に来るものです。改名が走るということは多くの場所に変更がなされていると推測でき、インストール方法もある程度変更されるであろうことから、これまでのように簡単にはいかなくなるであろう、少なくとも改名後のアップデートは大変なものになるであろうと考えていました。

そして改名のお知らせが7月20日になった時、その懸念は現実のものとなってしまいました。そもそもGitリポジトリがCodebergから謎のsystemsで終わるサイトへ移動していました(その後 git.joinfirefish.org へ再移動)し、現在ではかなり解決されていますがまるで単にs/Calckey/Firefishを実行しただけのような公式サイトでしたので、エスパーをしつつリンクを手元で修正しながら情報を集めていました。

そのような状況でしたので7月中はCalckey 13.1.4.1を使い続けることにしていました。しかしながら古いソフトウェアは徐々に動かなくなりますし、動かなくなってからアップデートしようとすると苦しいことも知っていましたのでいつかはアップデートしようかと思い、「ubuntu-bash-install」の「update.ubuntu.sh」がいい感じになってからアップデートしようと思っていました。しかし8月に入っても特に進捗が見られず(私がやれ、というのはそれはそうなのですが)、思い切ってリリースノートと向き合うことにしました。

思ったよりシンプル

向き合ってみると意外や意外、思ったよりシンプルであることが分かりました。バージョン1.0.0のリリースノートは当然ながらバージョン1.0.0ですので、色々なことが書いてありますが、きちんと読み込めばgit clonepm2とRustを入れ、NODE_ENV=production pnpm run build && pnpm run migrateをしてpm2 start "NODE_ENV=production pnpm run start" --name Firefishをすればよいと分かります。というわけでやっていきましょう。

まずはaptを用いて各種パッケージを更新しておきます。

sudo apt update
sudo apt upgrade

またケチケチインスタンスですし、割り当てているSSDの容量もものすごく多いわけではないので、使われていないパッケージやdebファイルもお掃除してもらいましょう。まあそんなには空きませんが…

sudo apt autoremove
sudo apt autoclean

その後rebootを掛け、ここからはCalckeyを実行していたユーザーで実行します。と思ったのですがCalckeyユーザーのパスワードを忘れていたのでpasswdコマンドを利用し変更します。大変に体験型学習ですね。

sudo passwd <Calckeyのユーザー名>
新しい パスワード:
新しい パスワードを再入力してください:
passwd: パスワードは正しく更新されました 

さてCalckeyの実行ユーザーでログイン出来ました。それではCalckeyが置いてあるリポジトリへ移動します。また念のため(普通にインストールすれば入っているかと思いますが)gitが使えることと.gitディレクトリがあることを確認しておきます。

git --version
git version 2.34.1

ls -a
.               .okteto             COPYING              chart     gulpfile.js           pnpm-workspace.yaml
..              .vim                Dockerfile           cliff.toml     issue_template        release.json
.config         .vscode             LICENSE              custom     kubernetes-README.md  rome.json
.dockerignore   .vsls.json          Procfile             cypress     locales               scripts
.editorconfig   .woodpecker         README.md cypress.config.ts   node_modules          title_float.svg
.git            CALCKEY.md          SECURITY.md          dev     package.json
.gitattributes  CHANGELOG.md        built docker-README.md    packages
.gitignore      CODE_OF_CONDUCT.md  calckey.apache.conf docker-compose.yml  patrons.json
.node-version   CONTRIBUTING.md     calckey.nginx.conf   files     pnpm-lock.yaml 
cd .git
vim config

きちんと存在が確認できたので、originを変更し最新のコードを取得します。

git remote set-url origin https://git.joinfirefish.org/firefish/firefish.git
git pull -ff

上手くいきましたね。ではビルドのための下準備をします。まずはNodejsのバージョンを確認します。

node --version
v18.17.0

リリースノートを見ると最新バージョンが推奨されているのでこれをインストールします。aptでもNodejsをインストールは出来ますが、バージョンがめちゃくちゃ古いのでnという検索性が最悪の名前をしたバージョン管理ツールを用いて最新版を入れます。

npm install -g n
su <スーパーユーザー>
sudo n latest

いい感じにインストール出来ました。ではcorepackをオンにした上でRustをインストールします。注意点としてはスーパーユーザーのまま実行する必要があるという点くらいでしょうか。

corepack enable
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 

ここで問題が無ければCalckey実行ユーザーに戻ります。Firefishへの改名に伴い設定ファイルを書き換える必要がありますが、Firefishで追加された新機能を使わないのであればいじる必要はほとんどありません。適宜行いたい方はやるといいでしょう。

メモリが足りないケチケチインスタンス

ではビルドという沼に入っていこうかと思います。念のためrebootを掛けた上で、まずはpnpmを用いてライブラリのインストールを行います。

pnpm i

インストールが終わったのならば、ビルドとマイグレーションを行います。

NODE_ENV=production pnpm run build && pnpm run migrate 

これで上手くいけば良かったのですが、以下のようなログを吐かれ上手くいきませんでした。

> [email protected] build /home/calckey/calckey
> pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp

 ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄▄   ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄▄▄ ▄▄   ▄▄    ◯
█       █   █   ▄  █ █       █       █   █       █  █ █  █      ○   ▄    ▄
█    ▄▄▄█   █  █ █ █ █    ▄▄▄█    ▄▄▄█   █  ▄▄▄▄▄█  █▄█  █    ⚬     █▄▄  █▄▄
█   █▄▄▄█   █   █▄▄█▄█   █▄▄▄█   █▄▄▄█   █ █▄▄▄▄▄█       █      ▄▄▄▄▄▄   ▄
█    ▄▄▄█   █    ▄▄  █    ▄▄▄█    ▄▄▄█   █▄▄▄▄▄  █   ▄   █     █      █  █▄▄
█   █   █   █   █  █ █   █▄▄▄█   █   █   █▄▄▄▄▄█ █  █ █  █     █ ● ●  █
█▄▄▄█   █▄▄▄█▄▄▄█  █▄█▄▄▄▄▄▄▄█▄▄▄█   █▄▄▄█▄▄▄▄▄▄▄█▄▄█ █▄▄█     ▀▄▄▄▄▄▄▀
 Currently building Firefish!
 Hang on for a moment, as this may take a while.

Scope: 6 of 7 workspace projects
packages/backend build$ pnpm swc src -d built -D
packages/backend/native-utils build$ pnpm run build:napi && pnpm run build:migration
packages/client build$ pnpm vite build
packages/firefish-js build$ pnpm swc src -d built -D
packages/megalodon build$ tsc -p ./
packages/sw build$ webpack
packages/backend/native-utils build: > [email protected] build:napi /home/calckey/calckey/packages/backend/native-utils
packages/backend/native-utils build: > napi build --features napi --platform --release ./built/
packages/firefish-js build: Successfully compiled: 8 files with swc (129.25ms)
packages/firefish-js build: Done
packages/backend build: Successfully compiled: 871 files, copied 21 files with swc (737.64ms)
packages/backend build: Done
packages/sw build: Done
packages/megalodon build: Done
packages/backend/native-utils build:  Downloading crates ...
packages/backend/native-utils build:   Downloaded convert_case v0.6.0
packages/backend/native-utils build:   Downloaded ctor v0.2.2
packages/backend/native-utils build:   Downloaded napi-derive v2.13.0
packages/backend/native-utils build:   Downloaded napi v2.13.1
packages/backend/native-utils build:   Downloaded napi-sys v2.2.3
packages/backend/native-utils build:   Downloaded bitflags v2.3.1
packages/backend/native-utils build:   Downloaded napi-derive-backend v1.0.52
packages/backend/native-utils build:    Compiling autocfg v1.1.0
packages/backend/native-utils build:    Compiling proc-macro2 v1.0.59
packages/backend/native-utils build:    Compiling quote v1.0.28
packages/backend/native-utils build:    Compiling unicode-ident v1.0.9
packages/backend/native-utils build:    Compiling version_check v0.9.4
packages/backend/native-utils build:    Compiling libc v0.2.145
packages/backend/native-utils build:    Compiling syn v2.0.18
packages/backend/native-utils build:    Compiling cfg-if v1.0.0
packages/backend/native-utils build:    Compiling memchr v2.5.0
packages/backend/native-utils build:    Compiling typenum v1.16.0
packages/backend/native-utils build:    Compiling cc v1.0.79
packages/client build: <--- Last few GCs --->
packages/client build: [1408:0x5b41920]    41143 ms: Scavenge 474.2 (486.5) -> 473.1 (486.8) MB, 7.79 / 0.00 ms  (average mu = 0.540, current mu = 0.454) allocation failure;
packages/client build: [1408:0x5b41920]    41149 ms: Scavenge 474.7 (486.8) -> 473.5 (487.3) MB, 3.25 / 0.00 ms  (average mu = 0.540, current mu = 0.454) allocation failure;
packages/client build: [1408:0x5b41920]    41424 ms: Scavenge 475.0 (487.3) -> 473.9 (491.5) MB, 267.77 / 0.00 ms  (average mu = 0.540, current mu = 0.454) allocation failure;
packages/client build: <--- JS stacktrace --->
packages/client build: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
packages/client build:  1: 0xc98550 node::Abort() [node]
packages/client build:  2: 0xb700a7  [node]
packages/client build:  3: 0xebae50 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
packages/client build:  4: 0xebb137 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
packages/client build:  5: 0x10cc7a5  [node]
packages/client build:  6: 0x10e4628 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
packages/client build:  7: 0x10ba741 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
packages/client build:  8: 0x10bb8d5 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
packages/client build:  9: 0x1098e46 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
packages/client build: 10: 0x14f3c76 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
packages/client build: 11: 0x192def6  [node]
packages/client build: undefined
packages/client build:  ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command was killed with SIGABRT (Aborted): vite build
packages/backend/native-utils build:    Compiling lock_api v0.4.10
packages/client build: Failed
/home/calckey/calckey/packages/client:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  client@ build: `pnpm vite build`
Exit status 1
 ELIFECYCLE  Command failed with exit code 1. 

パッと見ただけでは何が起きているのかよく分からない量のものですが、これも気合を出して向き合ってみるとどうやら「FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory」というのが主な原因のようです。これはNodejsの持っている ガベージコレクションが上手くいかず、メモリが足りなくなってしまう といった事象が起きていることを示しています。

本質的にはRAMを増やすべきなのですが、伝家の宝刀†スワップファイル†を用いている関係でそんなことが出来るはずありません。適当に調べて出てきた「JavaScript heap out of memory が発生したときに試したこと」というページを参考に、以下のようなコマンドを実行してみました。

NODE_ENV="production --max_old_space_size=3072" pnpm run build && pnpm run migrate

しかしながらこれでも同様のエラーが出てしまいました。割り当てているメモリの容量が足りないのかと考え、スワップの設定を変更しながらmax_old_space_size=6144まで試してみましたが上手くいく気配はありませんでした。もう一度先程参考にしたページを見てみると、オプションが実際に実行されるコマンドまで渡っていない可能性について触れられていました。確かに一理あります。

というわけで直接渡してみましょう。Vimを用いてpackage.jsonを編集します。何行目かは忘れたのですが真ん中あたりにビルドに関する設定がありますので、pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulpを、pnpm node ./scripts/build-greet.js && NODE_OPTIONS=--max_old_space_size=3072 pnpm -r --parallel run build && pnpm run gulp という風に編集します。こうすることによって、コケていた2番目のコマンドが実行される際、確実にメモリが確保出来るようになります。保存した後に以下のコマンドを実行します。

NODE_ENV=production pnpm run build && pnpm run migrate 

これで失敗していたのならばもっとこの記事を膨らませることが出来たのですが、幸いなことに上手くいってしまいました。Rust関係のビルドに15分くらいかかりものすごく不安だったのですが、特に問題なく上手くいきました。ちょっと残念ですが悲しいことではないので、これを公開できるようにします。

上の方でpm2は入れていたのですが、パッケージを入れ忘れていたのでインストールします。

pm2 install pm2-logrotate 

その後、以下のコマンドを実行します。

pm2 start "NODE_ENV=production pnpm run start" --name Firefish 

ここにおいてエラーが出なければ、以前Calckeyを動かしていたドメイン(私の場合はc.osumiakari.jp)へとアクセスすると、Firefishが動いている様子が見られるはずです。お疲れさまでした!

関連リンク

最後に

というわけで参考になるような人が少ないようなアップデートの記録でした。ケチケチインスタンスを運用されている方の参考になればいいなとは思うのですが、普通は余裕を持ったスペックのマシンを用意するので、やっぱり参考になるような人がいないと嬉しいなと思います。

Writer

Osumi Akari