Edited at

Mastodon 保守メモ

備忘録として残しておきます

Mastodon専用ユーザにて、Mastodonのインストールディレクトリにて操作することを前提にしています。

(非Dockerならliveディレクトリ)


参考資料


tootctl

v2.5.0より、tootctlというコマンドラインツールが追加された。

Rakeタスクでの引数指定方法等への不満から誕生したものである。

既存Rakeタスクは、初期セットアップに使う一部のものを除き、tootctlに置き換えられた。


tootctl(v2.8.1)

$ RAILS_ENV=production bundle exec bin/tootctl help

Commands:
tootctl accounts SUBCOMMAND ...ARGS # Manage accounts
tootctl cache SUBCOMMAND ...ARGS # Manage cache
tootctl domains SUBCOMMAND ...ARGS # Manage account domains
tootctl emoji SUBCOMMAND ...ARGS # Manage custom emoji
tootctl feeds SUBCOMMAND ...ARGS # Manage feeds
tootctl help [COMMAND] # Describe available commands or one specific command
tootctl media SUBCOMMAND ...ARGS # Manage media files
tootctl search SUBCOMMAND ...ARGS # Manage the search engine
tootctl self-destruct # Erase the server from the federation
tootctl settings SUBCOMMAND ...ARGS # Manage dynamic settings
tootctl statuses SUBCOMMAND ...ARGS # Manage statuses
tootctl version # Show version


tootctl の実体

https://github.com/tootsuite/mastodon/tree/master/lib/mastodon

このあたりにある *_cli.rb が実体


Rakeタスク

https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/List-of-Rake-tasks.md

あるいは

# すべてのRakeタスクを表示

$ RAILS_ENV=production bundle exec rails -T

# Namespace "mastodon" のタスクのみ表示
$ RAILS_ENV=production bundle exec rails -T mastodon

で、定義されているタスクが一覧(+簡単な説明文)表示される。

v2.6.1で確認したところでは、殆どの管理タスクがtootctlに移行されている。

タスク一覧の出力例


mastodon_tasks(v2.6.1)

$ RAILS_ENV=production bundle exec rails -T mastodon

rails mastodon:setup # Configure the instance for production use
rails mastodon:stats # Report code statistics (KLOCs, etc)
rails mastodon:webpush:generate_vapid_key # Generate VAPID key



Rakeタスクの実体

https://github.com/tootsuite/mastodon/tree/master/lib/tasks


Rails Consoleへの入り方


非Docker

$ pwd

/home/mastodon/live
$ RAILS_ENV=production bundle exec rails console
irb(main):001:0>


Docker

$ docker-compose run --rm web rails console

irb(main):001:0>

※ Docker環境がないので、動作確認はしていません


アカウント系(accounts)


アカウントを承認する(approve) [v2.8.0~]

登録が承認制の場合、保留中のアカウントを承認する。

$ RAILS_ENV=production bundle exec bin/tootctl accounts approve [USERNAME]

Option
Description

--number=N
承認するアカウント数を指定する。 規定値は指定なし

-n=N

numberの短縮形

--all
保留中のアカウントをすべて承認する。規定値は指定なし

ユーザ名を指定するか、--numberあるいは--allのどちらかを付ける必要がある。


アカウントを追加する(create)

$ RAILS_ENV=production bundle exec bin/tootctl accounts create [USERNAME] [OPTIONS]

OK
New password: [AUTO_GENERATED_PASSWORD]

Option
Description

--email
ユーザのメールアドレスを指定する。必須。

--role (admin|moderator|user)
ユーザ権限を指定する。規定値はuser(一般ユーザ)

--reattach
古いアカウントを引き継ぐ?(要検証) 規定値はなし

--force

--reattachが指定されたとき、古いアカウントを誰かが使っていた場合、古いレコードを削除し新しいユーザに引き継ぐ?(要検証)規定値はなし


  • ユーザ名とメールアドレスは必須

  • パスワードはランダムに生成される(作成後に表示される)

  • 確認済みステータスになる


  • reattach は、アカウントの切り替え(実質アカウント名の変更)に使用するようだ

Rakeタスクを使う場合 (v2.5.0以前)

$ RAILS_ENV=production bundle exec rails mastodon:add_user

ユーザー名、メールアドレスを聞いてくるので入力する。



アカウントを削除する(delete) [v2.6.1~]

サスペンド状態になる。

過去の投稿はすべて削除される。

$ RAILS_ENV=production bundle exec bin/tootctl accounts delete [USERNAME]


[moved] メールアドレスを確認する

v2.6.1以降の情報は、「ローカルアカウントの編集を行う」に集約してあります。

Rakeタスクを使う場合 (v2.5.0以前)

$ RAILS_ENV=production bundle exec rails mastodon:confirm_email USER_EMAIL=hoge@example.tld



[moved] 特定のユーザを管理者あるいはモデレータにする、権限を剥奪する

v2.6.1以降の情報は、「ローカルアカウントの編集を行う」に集約してあります。

Rakeタスクを使う場合 (v2.5.0以前)


管理者

$ RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME=hogehoge


モデレータ

$ RAILS_ENV=production bundle exec rails mastodon:make_mod USERNAME=hogehoge


権限を剥奪(一般ユーザ化)

$ RAILS_ENV=production bundle exec rails mastodon:revoke_staff USERNAME=hogehoge



ローカルアカウントの編集を行う(modify) [v2.6.1~]

$ RAILS_ENV=production bundle exec bin/tootctl accounts modify [USERNAME] [OPTIONS]

Option
Description

--email
ユーザのメールアドレスを指定する。上書きされる。

--confirm
メールアドレスを確認済みにする

--role (admin|moderator|user)
ユーザ権限を指定する。

--enable
アカウントロックを解除する(使用可能になる)

--disable
アカウントロックを行う(使用不能になる)

--disable_2fa
二段階認証を無効にする

アカウント名の変更を行う場合は、create--reattachオプションを使用する。

(新しいアカウントを作って、各種情報の紐づけなおしのようなイメージ)


管理者とモデレータの権限比較 [v2.8.0]


モデレーションメニュー

操作
備考
管理者
モデレータ

操作履歴
管理・モデレーション画面の操作履歴

通報
通報の確認、コメント、対応

アカウント
アカウント一覧、確認、編集等

招待
招待URLの生成
△(設定による)
△(設定による)

ハッシュタグ
プロフィールのタグをディレクトリに出すかどうか

既知のサーバー
他サーバの一覧、ドメインブロック

×

メールブロック
メールのドメインブロックの追加、削除

×


管理メニュー

操作
備考
管理者
モデレータ

ダッシュボード
稼働状況の概略表示

サイト設定
Mastodonの基本設定

×

カスタム絵文字
カスタム絵文字の一覧

カスタム絵文字
カスタム絵文字の登録(コピー)

×

カスタム絵文字
カスタム絵文字の無効化

カスタム絵文字
カスタム絵文字の削除

×

リレー
連合リレーへの参加

×

バックエンド情報の表示
WebSub、Sidekiq、PgHeroへのアクセス

×

モデレータ権限でも、ローカルユーザのメールアドレスとか見えちゃうので

信頼のおける人にだけ権限を付与しよう!

※ただし、パスワードは暗号化されて格納されており、管理者でも見えない。パスワード忘れの際はリセットするしかない。


存在しないリモートユーザを削除する(cull)

リモートユーザが本当に存在するか実際に問い合わせを行い、存在しなければ削除する。

$ RAILS_ENV=production bundle exec bin/tootctl accounts cull

...............................(中略).........................................
Removed 0000 accounts. 0000 servers skipped
The following servers were not available during the check:
hoge.example.com
fuga.example.jp

Option
Description

--dry-run
存在チェックのみ行い、データのパージは行わない。規定値はなし

進捗具合は「.」で表示される。

無効になっている(HTTP 404/410が返された)外部ユーザは緑色の「」で表示され、ローカルから削除される。

(環境によっては緑色表示にならない場合もある)

調査中、何件かエラーが続いたらそのサーバの調査をスキップする。

サーバの規模(認知している外部ユーザ数)にもよるが、かなりの時間がかかる。

進捗は「.」による表示のみのため、完了時間の予測が立てられない。

バックグラウンドで動かしておくとよいと思われる。

Rakeタスクを使う場合 (v2.5.0以前)

$ RAILS_ENV=production bundle exec rails mastodon:maintenance:purge_removed_accounts

オプションとして -- -f あるいは -- --force を与えると、確認メッセージ無しで削除を実行する。

リモートに存在せず(HTTP 404ないし410が返された場合)、

かつパージを明示的に指示した場合、そのアカウントをパージ、つまり 抹消する

証明書切れ、DNS名前解決に失敗、HTTP 404/410以外のエラーコードが返されたとき、などはスルーされる。

(メンテナンス作業中であった場合等を考慮した措置だと思われる)

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



ユーザ情報のバックアップを生成する(backup) [v2.6.1~]

ここで言うバックアップとは、アーカイブのことである。

Web UIの「設定」→「データのエクスポート」→「アーカイブデータのリクエスト」を行うことと同義。

実行すると、バックグラウンドで生成処理が行われる。

$ RAILS_ENV=production bundle exec bin/tootctl accounts backup [USERNAME] 


特定のユーザをローカルユーザ全員にフォロー・アンフォローさせる(follow/unfollow) [v2.7.0~]

外部サーバのユーザに対してフォロー・アンフォローを投げることも可能。

(その場合はACCTにフルハンドルを指定する)

たとえば、サーバ情報を配信するアカウントの新設・変更・廃止などを行う場合に有効かもしれない


フォローさせる(follow)

$ RAILS_ENV=production bundle exec bin/tootctl accounts follow [ACCT] 


アンフォローさせる(unfollow)

$ RAILS_ENV=production bundle exec bin/tootctl accounts unfollow [ACCT] 


ユーザのリレーションシップをリセットする(reset-relationships) [v2.8.0~]

(未検証)

指定したユーザのフォロー・フォロワーをリセットする。

$ RAILS_ENV=production bundle exec bin/tootctl accounts reset-relationships [USERNAME] 

Option
Description

--follows
指定したユーザのフォローをすべて外す。規定値は指定なし

--followers
指定したユーザのフォロワーをすべて外す。規定値は指定なし

--followsあるいは--followersのいずれか、もしくは両方を指定する必要がある。


ユーザのRSA鍵を再生成しブロードキャストする(rotate) [v2.6.1~]

ユーザのRSA鍵を再生成し、外部のサーバに配信する。

セキュリティメンテナンスに使用する?

$ RAILS_ENV=production bundle exec bin/tootctl accounts rotate [USERNAME] [OPTIONS]

Option
Description

--all
すべてのユーザを対象とする。これを付けない場合は、ユーザ名の指定が必須。規定値は指定なし


外部サーバのユーザの情報を更新する(refresh)

$ RAILS_ENV=production bundle exec bin/tootctl accounts refresh [USERNAME] 

OK

アイコン、ヘッダー、自己紹介文などを取得しなおす。

Option
Description

--domain [DOMAIN]
特定のドメインに対して実行する。これを指定しない場合はユーザ名の指定が必要。規定値は指定なし

--all
全リモートユーザに対して実行する。これを指定しない場合はユーザ名の指定が必要。規定値は指定なし

ユーザ名を指定せず、--domainあるいは--allを指定した場合、Sidekiqキューに積まれる。

Rakeタスクを使って、全サーバを対象に実行する場合 (v2.5.0以前)

全サーバに対して行う場合は、Rakeタスクが用意されている。

時間がかかる上、エラー落ちすることがあるので注意。

$ RAILS_ENV=production bundle exec rails mastodon:media:redownload_avatars


Railsコンソールから実行する場合

特定のサーバに属するユーザを対象にするなど、スコープをカスタマイズしたい場合は、下記Rails Consoleコードを実行する。

where部分を書き換えたり追加したりすれば、様々な条件で引っ掛けることが可能

Account.where(domain: "nagoyadon.jp").find_each do |account|

printf("%s@%s\n", account.username, account.domain)
account.reset_avatar!
account.reset_header!
account.save
end; 0

引っ掛けられるカラムは、モデルを見ればだいたい分かるかも

https://github.com/tootsuite/mastodon/blob/master/app/models/account.rb



キャッシュ系(cache)


Railsキャッシュをクリアする(clear)[v2.8.1~]

Railsアプリのキャッシュを消去する。オプションはない。

$ RAILS_ENV=production bundle exec bin/tootctl cache clear

内部的には、シンプルにRails.cache.clearをキックしている。


ドメイン系(domains)


外部サーバをパージする(purge)[v2.6.1~]

確実に閉じた、あるいは復旧の見込みがない外部サーバをパージ(切り離し)する。

そのサーバから転送されてきた投稿等はすべて削除される。

$ RAILS_ENV=production bundle exec bin/tootctl domains purge [DOMAIN]


purgeしたサーバが復活したらどうなるの?

新しく発見したサーバ扱いになります。

ただし、フォロー関係に不整合が発生することがあります

(自分から見るとフォロワーから外れているのに、相手から見るとフォローされた状態、など)


統計情報を取得する(crawl)[v2.7.0rc3~]

認知しているすべてのサーバに対し、統計情報の問い合わせを行い

観測範囲内の統計情報を生成する

$ RAILS_ENV=production bundle exec bin/tootctl domains crawl

Option
Description

--concurrency
HTTPリクエストのスレッド数。規定値は50

-c

--concurrency の省略形

--silent
進捗のドットを表示しない。規定値は指定なし(表示する)

-s

--silent の省略形

--format
出力フォーマットを指定する。jsonsummarydomainsのいずれかを指定する。規定値はsummary

-f

--format の省略形


summary出力例

$ RAILS_ENV=production bundle exec bin/tootctl domains crawl

..................... (中略) .............................
Visited 11658 domains, 6143 failed (1805s elapsed)
Total servers: 3196
Total registered: 1870253
Total active last week: 167957
Total joined last week: 20305

フォーマットとして json を指定した場合、 検出したすべてのサーバの情報が出力される。

膨大な量になるため、--silentオプションを付けたうえでファイルへリダイレクトするなど適宜工夫されたい。

また、domainsフォーマットを指定した場合、検出したすべてのドメインが一覧で出力される。(それ以外の情報は表示されない)

これも膨大な量のため注意されたい。

内部的には、api/v1/instanceapi/v1/instance/peersapi/v1/instance/activityの3つのエンドポイントにアクセスし情報を取得しようとする。

そのうちどれか一つでも失敗(HTTP 200以外のレスポンスが返された)すれば、それはfailedに計上される。

報告される登録者数等は、各サーバからのレスポンスを基にするため、悪意あるサーバが不正な値を返した場合、あり得ない数字になったりする。

また、検出中にサーバダウンしていた場合などはもちろん計上されないため、正確な数字ではない。参考程度にするとよい。


カスタム絵文字系(emoji)


カスタム絵文字をインポートする(import)[v2.6.1~]

未検証

GZipされたTARアーカイブからカスタム絵文字をインポートする。

ファイルの拡張子は.pngである必要がある。

ショートコードとして、拡張子を除いたファイル名が使われる。

$ RAILS_ENV=production bundle exec bin/tootctl emoji import [PATH]

Option
Description

PATH
GZipされたTARアーカイブ(.tar.gz等)へのパス。

--prefix=PREFIX
ショートコードの接頭辞を指定する。規定値は指定なし

--suffix=SUFFIX
ショートコードの接尾辞を指定する。規定値は指定なし

--overwrite
これを付けると、同じショートコードの絵文字があった場合上書きする。規定値は指定なし(上書きしない)

--unlisted
これを付けると絵文字ピッカーに表示しない。規定値は指定なし(絵文字ピッカーに表示する)

(v2.6.1でのヘルプテキストに不備があり、実際はGZipされたTARアーカイブである必要がありました)


全てのカスタム絵文字を消す(purge)[v2.8.0~]

未検証

登録されているカスタム絵文字をすべて削除する

$ RAILS_ENV=production bundle exec bin/tootctl emoji purge

オプションはない。


フィード系(feeds)

ホームタイムラインが表示されない(Redisのデータが壊れた)時などに復旧させるためのコマンド類。


ホーム・リストタイムラインのフィードをクリアする (clear)

$ RAILS_ENV=production bundle exec bin/tootctl feeds clear

OK

オプションはない。

全ユーザのフィードが削除される。

タイムラインが壊れたとしても、後述するbuildを流せばよく、敢えて削除する必要はないのかもしれない。


ホーム・リストタイムラインのフィードを再構築する (build)

$ RAILS_ENV=production bundle exec bin/tootctl feeds build [USERNAME]

Option
Description

--all
全ユーザに対して実行する。規定値は指定なし

--background
バックグラウンド(Sidekiqキュー)で実行する。高速。規定値は指定なし

--dry-run
実際には実行しない。規定値は指定なし(実際に実行する)

--verbose
処理の詳細情報を表示する。規定値は指定なし

--verboseを付加すると、フォアグラウンドで実行され、処理が終わったアカウントIDを列挙する。

Rakeタスクを使う場合 (v2.5.0以前)

$ RAILS_ENV=production bundle exec rails mastodon:feeds:build



メディアファイル系(media)


外部サーバの古いメディアファイルを消す(remove)

デフォルトでは7日以前のメディアファイルを消す

$ RAILS_ENV=production bundle exec bin/tootctl media remove

Option
Description

--days=N
N日前までのメディアファイルを消す。規定値はN=7(日)

--background
削除処理をバックグラウンドで行う(Sidekiqを使用する)。

--no-background
削除処理をフォアグラウンドで行う。規定値

--verbose
バックグラウンド処理でない場合、コンソールに処理対象のIDを表示する。規定値は指定なし

--dry-run
対象を検索するのみで、実際の削除処理を行わない。規定値は指定なし

バックグラウンド処理を指定した場合、Sidekiqを使用して並列実行を行うため、効率よく処理を行える一方で、他キューの実行遅延・ストレージに対し負荷がかかることが想定されるので、注意が必要。

また、オブジェクトストレージを使用している場合は、DoS攻撃と間違われ規制を受ける可能性が捨てきれないので、特に注意されたい。

Rakeタスク (v2.5.0以前)

$ RAILS_ENV=production bundle exec rails mastodon:media:remove_remote



古いPreviewCardを削除する

v2.9.2現在、tootctl にはそのようなコマンドはない。

Railsコンソールより下記コードを実行することにより、古いものを削除することができる。

1つ1つは小さいが、毎日それなりの勢いで蓄積されていくので、いずれは対処せねばならない問題だと感じている。


PreviewCardお掃除


# どれだけの数があるか、また削減できる容量がどれだけかを確認するだけの場合は、コメントつきのまま実行する。

total_num = 0; 0
total_size = 0; 0

# 下記のwhere句を変更すれば、任意の範囲・条件で絞り込むことが可能。
PreviewCard.where("updated_at < ?", 180.days.ago).find_each do |card|

total_num = total_num + 1
if card.image_file_size != nil then
total_size = total_size + card.image_file_size

# プレビューカードの画像だけ削除する場合は、下の2行のコメントを外して実行する。
# card.image.destroy!
# card.save!
end

# プレビューカードごと削除する場合は、下の1行のコメントを外して実行する。
# card.destroy!

end; 0

printf("%d card(s), %d MBytes reduced\n", total_num, total_size/1.megabytes)



PreviewCardそのものをdestroyした時の挙動


  • そのURLに対するプレビューカードが表示されなくなる。

  • そのURLが含まれる投稿に対して、FavやブーストなどのアクションをしてもPreviewCardの再取得は行われない。

  • 後に同一のURLが新規に投稿されたとき、新たにプレビューカードの取得が行われる。


PreviewCardのimageだけをdestroyした時の挙動



  • そのURLに対するプレビューカードは表示されたままになる。 ただし、画像部分に関してはデフォルトの画像が表示される。

  • そのURLが含まれる投稿に対して、Favやブーストなどのアクションをしても、画像の再取得は行われない。

  • 後に同一のURLが新規に投稿されても、 再度、画像の取得が行われることはない。


懸念事項


  • 検索条件としてupdated_atが一定以上古いもの、としているが、同一URLが投稿されたときにupdated_atが更新されているか未確認。つまり、初出は古いが頻出であるURLのPreviewCardがバッサリ消された場合、再度取得しに行くコストがかかる可能性が高くなる。

検証環境(v2.9.2)にて確認した挙動ですが誤りがあるかもしれません。

よっぽど大丈夫だとは思われますが、ほかの場所に影響が出る可能性も否定できないので、ご利用は自己責任で。

無理やりな感じなので、ほかによいやり方があれば教えてください。


全文検索系(search)


全文検索のインデックスを(再)生成する(deploy)[v2.8.0rc1~]

未検証

$ RAILS_ENV=production bundle exec bin/tootctl search deploy

オプションはない。


サーバを閉じる準備を行う(self-destruct)[v2.8.0rc1~]

サーバを連合から切り離し、安全に閉じられるようにする。

未検証

$ RAILS_ENV=production bundle exec bin/tootctl self-destruct

接続されているすべてのサーバに対しaccount deleteアクティビティを送信し、ほかのサーバからキャッシュを削除する。(厳密には、削除するよう促す。ほかの実装が対応しているとは限らないので完全消去は難しい)

ただし、実際にはローカルのデータは削除されない。

各ユーザのサスペンドフラグを立てるので、おそらくログインはできなくなる。

そのまま使い続けるとデータの不一致が発生し、どんな不具合をもたらすか分からない。

これを実行した後で、サーバを削除するか、データベース等を初期化してから再出発する必要がある。

自分が何をしているのか理解した上で実行すること


サーバ設定系(settings)


新規登録を制御する(registrations)[v2.6.1?~]

$ RAILS_ENV=production bundle exec bin/tootctl settings registrations [OPTION]

Option
Description

open
新規登録を有効にする。

close
新規登録を無効にする。


投稿系(statuses)


過去の投稿を削除する(remove)[v2.8.0rc1~]

$ RAILS_ENV=production bundle exec bin/tootctl status remove

Option
Description

--days=N
何日前の投稿を対象とするか。規定値は N=90(日)

以下の投稿は除外する。


  • ローカルユーザーによってフォローされているユーザーのもの

  • ローカルユーザーの投稿に対してリプライされたもの

  • ローカルユーザーによってお気に入りされたもの

  • ブーストされたもの

  • リプライであるもの

  • ピン止めされているもの


実行例

$ RAILS_ENV=production bundle exec bin/tootctl status remove --days=90

Creating temporary database indices...
Beginning removal... This might take a while...
Beginning removal of now-orphaned media attachments to free up disk space...
Done after 338.574609041214s
Removing temporary database indices to restore write performance...
$


removeしたけど空きディスク容量が増えないんだけど?

PostgreSQLでは、データ(行)を削除するだけでは、空きディスク容量は増えません。

削除したデータをお掃除(バキューム)する必要があります。

削除領域をOSに返すためにはVACUUM FULLを流します。

ただし、FULLの場合は排他ロックがかかるため、実行中はテーブルへのアクセスができません。

下の記事に少しメモってあります。

PostgreSQLのvacuumについて調べたメモ


バージョン情報を表示する(version)[v2.7.0rc3~]

$ RAILS_ENV=production bundle exec bin/tootctl version


出力例

2.7.0rc3



その他のタスク


[outdated] 誰もフォローしていないユーザの購読をパージ

連合タイムラインを整理したい時に。

v2.5.0まで

tootctl(v2.6.1) においては、代替コマンドはない。

$ RAILS_ENV=production bundle exec rails mastodon:push:clear


システム系


Mastodonサービスのログを見たいとき

$ sudo journalctl -r -u mastodon-web

$ sudo journalctl -r -u mastodon-sidekiq
$ sudo journalctl -r -u mastodon-streaming

-r で新しいものを先に表示

-u で表示するモジュールを指定

-f も付ければ、継続監視が可能(tailみたいに)


Nginxのログを見たいとき

$ sudo tail /var/log/nginx/access_log

$ sudo tail /var/log/nginx/error_log

継続して監視したい時は、 tail -f が便利


データベースなどのバックアップを取得したいとき

アップデート手順内にメモってあるので、それを参考に実施

( pg_dump でデータベースダンプファイル取得、tarでPublicディレクトリのアーカイブ化)

https://qiita.com/kumasun/items/f17754e57120f7b13a06


Ruby Gem を再インストールしたい時

稀に壊れたりすることがあるようです。。。

$ bundle pristine

thanks @theoria !

あるいは

$ bundle exec gem uninstall -aIx

$ bundle install

引数 -aIx で、「全てを確認無しでアンインストール」

その後、通常通りインストールする

bundler 経由で操作しないと、グローバル環境のGemに作用する?らしいので注意。


アセットをゼロから作り直したい時

$ RAILS_ENV=production bundle exec rails assets:clobber

$ RAILS_ENV=production bundle exec rails assets:precompile

clobber で webpackの出力を全消しできる


tootctlやrakeタスクをcronで動かしたいとき

cronから直接実行すると、環境変数が読み込まれず動作しない模様

たとえば、毎日0時0分にmedia removeを実行する場合は下記のようにする


crontab

0 0 * * * /bin/bash -l -c 'cd ~/live && RAILS_ENV=production bundle exec bin/tootctl media remove >> ~/log/media_remove.log 2>&1'


crontabでの時間指定の仕方については、ここでは省かせて頂く(検索するとたくさん出てくる)

実行するコマンドは任意のものをどうぞ


スパム対策

(他にやれそうなことがあったら教えてください)

公開していると、どうしてもスパムがやってきます。

それらの対策について、ケースごとに紹介します。

スパマー許すまじ


連合を組んだ他のサーバからスパム投稿が送られてくる場合


  • 特定のユーザからスパム投稿が行われている場合、そのユーザを「転送」を有効にして通報する。加えて、「モデレーション」画面から該当ユーザを探し、「サスペンド」「活動停止」を実行する。

  • 特定のサーバがスパムアカウントだらけになっており、まるごと封じたい場合は、管理者権限で「既知のサーバー」より「ドメインブロック」を行う。


自分のサーバにスパムアカウントが作られた場合


  • そのユーザを通報するか、「設定」→「モデレーション」画面から該当ユーザを探し、「サスペンド」「活動停止」を実行する。

  • 断続的に作られてしまって収拾がつかなくなってしまった場合は、いったん「サイト設定」内の「新規登録」を「誰も許可しない」に設定し、順次該当アカウントの「サスペンド」「活動停止」を実行する。

ただし、今あるスパムアカウントの対処し終わったからとって、何も対策せず再解放すると、再び嵐のようなスパム登録が行われる可能性が高いので、後述するメールブラックリストの設定や、Nginxでのアクセス制限を設定してから解放する。

新規登録を「承認制」もしくは「招待制」とすれば、ある程度抑制はできると思われるが、スパマーでない新規登録者も参加しづらくなる問題がある。


メールブラックリストの設定


メールアドレスのドメイン部を調べる

まず、スパムアカウントのメールアドレスのドメイン部を調べる。

たとえば、 alice@evil.example.com というメールアドレスが使われていた場合

ドメイン部は evil.example.com である。

まずこれを控えておく。


ドメインのMXレコードを調べる

MXレコード = 電子メールの配送先を示すDNSのレコード。

メールのドメイン部をころころ変えて登録してくるパターンでも、実はMXレコードは同じところを指し示して使い回しているケースがあり、その場合、それを抑えれば一網打尽にできる可能性がある。


MXレコードの調べ方

たとえば evil.example.com のMXレコードを調べたい時

nslookup を使う例。

Windows 10 / Linux(Fedora)にて動作確認。

$ nslookup -type=mx evil.example.com

Server: 192.168.xxx.xxx
Address: 192.168.xxx.xxx#53

Non-authoritative answer:
evil.example.com mail exchanger = 0 mail.evil.example.com.

Authoritative answers can be found from:

dig を使う例。

Linux(CentOS)にて動作確認。

$ dig mx evil.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> mx evil.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34355
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1280
;; QUESTION SECTION:
;evil.example.com. IN MX

;; AUTHORITY SECTION:
evil.example.com. 299 IN SOA mail.evil.example.com. 1 3600 300 2419200 300

;; Query time: 351 msec
;; SERVER: xxx.xxx.xxx.xxx#53(xxx.xxx.xxx.xxx)
;; WHEN: Wed Jul 25 14:28:50 JST 2018
;; MSG SIZE rcvd: 127

この結果から、メールの配送先は mail.evil.example.com であることが分かる。

これも控えておく。


メールブラックリストの追加を行う


  • Mastodonに管理者権限でログインし、「設定」→「モデレーション」→「メールブラックリスト」の画面へ行く。

  • 上記手順にて調べた「メールアドレスのドメイン部」「MXレコード」を新規追加する。


Nginxでのアクセス制限の設定

どうしてものときの最終手段。

ちょっと複雑です。


スパマーのIPレンジを調べる


  • 「設定」→「モデレーション」画面から該当ユーザを探し、「直近のIP」を控える。(例:192.168.0.5)

  • IPの範囲を検索し、CIDR表記にする。(例:192.168.0.0/24)

CMAN ドメイン/IPアドレス サーチ などを使うと調べられるかも?


  • ブラックリスト用ファイルを作成し、CIDR表記を書き込む。(ファイルの場所は任意)

$ sudo vim /etc/nginx/conf.d/blacklist.conf


/etc/nginx/conf.d/blacklist.conf

deny 192.168.0.0/24;



  • Nginxの設定ファイルにブラックリスト用ファイルを読み込ませる一文を追加する


/etc/nginx/conf.d/mastodon.conf

(前略)

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

(中略)

include /etc/nginx/conf.d/blacklist.conf;

(後略)
}


※この例では、Mastodon全体にアクセス制限をかけているが、includeを書く場所を工夫することによって特定のURIのみ制限をかけることも可能


  • Nginxを再起動する

$ sudo nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo systemctl restart nginx


パフォーマンスチューニング

(他にやれそうなことがあったら教えてください)


PostgreSQL


サーバスペックに応じたパラメータを設定する

たとえば、pgTune( http://pgtune.leopard.in.ua/ )を参考に、サーバのスペックに合ったパラメータを設定する。


Socketを使う

Unix Socketを使うことで、localhost接続よりも高速化が可能となる。


/var/lib/pgsql/data/postgresql.conf

unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories


デフォルトでは /tmp をソケットディレクトリとして使用する。任意の場所に変更したりする。

設定を変更したら、PostgreSQLサービスを再起動する。


/home/mastodon/live/.env.production

DB_HOST=/var/run/postgresql


設定を変更したら、Mastodonサービス3点セットを再起動する。


pgBouncer を使う

PgBouncer とは


PgBouncer は、軽量なコネクションプーラーです。

通常、クライアントからデータベースに対して大量の接続が発生すると、接続を確立する為の時間のコストや、接続を管理する為のコンピュータリソースが多く必要となります。

このようなケースにおいて PgBouncer を使用すると、これらのコストを劇的に減少させる事ができます。

http://postgres.sios.com/modules/newbb/viewtopic.php?forum=1&topic_id=149&post_id=150


コネクションの開閉にはそこそこパワーを使うので、プールしておいて有効に使おうよ、という仕組み。

Mastodon公式ドキュメントにも、pgBouncerに関する記事がある。

tootsuite/documentation - PgBouncer Guide


Redis


Socketを使う

PostgreSQLと同様、Unix Socketを使うことで、localhost接続よりも高速化が可能となる。


/etc/redis.conf

unixsocket /var/run/redis/redis.sock

unixsocketperm 777

デフォルトではソケットを使用しない設定になっているので、コメントアウトし任意の場所に変更する。

設定を変更したら、Redisサービスを再起動する。


/home/mastodon/live/.env.production

REDIS_URL=unix:///var/run/redis/redis.sock

#REDIS_HOST=127.0.0.1
#REDIS_PORT=6379
#REDIS_PASSWORD=

設定を変更したら、Mastodonサービス3点セットを再起動する。


Mastodon

Tuning Mastodon


jemalloc を使ってメモリ最適化

jemallocとは?


jemalloc は、標準ライブラリで定義されているmalloc, free 等のメモリアロケーション APIの実装である。

http://zonomasa.hatenablog.com/entry/jemalloc_about


詳しい機能については引用元のWebページを参考にして頂きたいが、わたしのざっくりとした理解では:


  • メモリのフラグメンテーションを防止し、有効に使われるようにする

  • マルチコア・スレッド環境においてパフォーマンス向上

  • メモリ周りの不具合(リーク、オーバーフロー等)の検査ツール付

また、このパッケージについて公式ドキュメントでも紹介されている。

Tuning Mastodon - Using jemalloc

Debian系(Ubuntu等)においては、上記公式ドキュメント通りに設定すればよいが、Fedoraにおいてはパッケージ名等が違うので注意が必要。


  • パッケージ名: jemalloc (jemalloc-5.0.1-5.fc28.x86_64 等)

  • インストールパス: /usr/lib64/libjemalloc.so.2

(これは Fedora 28 x64における値なので、他の環境では異なる可能性があります)


yum-install

$ sudo yum install jemalloc

$ ls /usr/lib64/libjemalloc.so.2
/usr/lib64/libjemalloc.so.2

mastodon-web.service および mastodon-sidekiq.service に対し、

jemallocを読み込ませるため Environment="LD_PRELOAD=/usr/lib64/libjemalloc.so.2" を追記する。

(下記はwebの例だが、sidekiqも同じように追記する。)


mastodon-web.service

[Unit]

Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
Environment="LD_PRELOAD=/usr/lib64/libjemalloc.so.2"
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


編集後、更新されたファイルを再読み込みし、webとsidekiqを再起動する。

$ sudo systemctl daemon-reload

$ sudo systemctl restart mastodon-{web,sidekiq}

実際にjemallocを有効にした環境においては、pumasidekiqプロセスのメモリ使用率をそれぞれ2~3割程度削減することに成功した。


その他、非技術的な部分


  • ホスティングサービス等を使用せず、独自にサーバを立て、自分以外の第三者にも使用できる状態にした場合、各地域の総合通信局に「電気通信事業届出」をしておくべし。

  • 「サイト設定」内に連絡先を記載。メールアドレス、管理者欄を埋める。他のサーバのアカウントなどがあれば併記しておく。サーバに何かあったときに、誰かが知らせてくれるかも。


TODO


  • 可能な限りリリースに追従する。


あとがき


  • 自分用にメモした内容です。必要に応じて読み替えてください。

  • 使用は自己責任でお願いします

  • こうしたほうがいいよ的なアドバイスを頂けると大変助かります

  • 連絡先: Mastodon1, Mastodon2

以上