Help us understand the problem. What is going on with this article?

Mastodonあれこれ

■はじめに

これはフレカフェ&きりたん丼合同 Advent Calendar 2019 2日目の記事 です。
mastodonの個人インスタンスを2年ほど稼働させてきて、なんとなくわかってきた部分があるような気がするので記事にしてみます。
主に以下について書きます。

  • サーバのお引越し
  • チューニング
  • カスタマイズ

■サーバお引越し

これまで、AWS→PC(Ubuntu Desktop)→Mac mini→MacBook→PC(Ubuntu Server) と何度かお引越しをしてきたので、どんな風にお引越ししたか書きます。

お引越し元の「データベースアーカイブ」「メディアデータ」「SSL証明書」「.env.production」があれば、概ね引っ越しできるはずです。

お引越し先の準備

公式ガイド等を参考にセットアップします。mastodonのバージョンは引越し元と同じものにしないと災いが起こります。
素の状態での動作確認は、開発環境で行っておくと安心でしょう。(画像・動画投稿の動作確認など)

メンテナンス中画面の準備

お引越し中はMastodonに繋がらないので、利用者向けに「何をしているのか」「いつ終わるのか」をお知らせする画面を用意しておくと親切かもしれません。お引越し元/先両方に用意しました。(どっちのサーバに繋がってるかわかるようにした)

メンテナンス

参考にした記事
nginxでのメンテナンス画面表示

お引越し元の荷造り

「データベースアーカイブ」「メディアデータ」「SSL証明書」をお引越し先に送るために準備します。

データベースアーカイブ

データベースのバックアップデータを作成します。当然バックアップした後の変更分は持っていけないため、お引越し直前の戸締まりした後(サービス停止後)に行うと良いでしょう。

こんな感じのコマンドでバックアップできるはずです。
/usr/bin/pg_dump -Fc mastodon_production -U username -w > /pathto/backup20191202.dump

メディアデータ

画像や動画が入っているので、そこそこのボリュームがあります。不要なデータ等を予め削除しておいた方が荷物の量が少なくて済みます。(うちのインスタンスで20GB程度あったかも)

古いメディアデータの掃除コマンド(のヘルプ)
RAILS_ENV=production bundle exec bin/tootctl media help remove
RAILS_ENV=production bundle exec bin/tootctl preview_cards help remove

掃除を終えたら、以下を丸ごとコピーしておけばいいと思います。

~/live/public/system/*

引っ越し直前にコピーすると時間がかかりすぎるため、事前に(前日の夜中とか)一旦まるごとコピーしておき、引っ越し直前でrsyncコマンドで差分だけコピーするようにしておけば時短になります。
お引越し先に直接 scopy/rsync すれば楽かも。

S3にメディアを入れていて、これをお引越しするなら全部をダウンロードしないといけないです(多分)。
たしかこの記事を参考にしてダウンロードしました。ダウンロードするためにたくさんアクセスするため、料金は高くなるかもしれません。

SSL証明書

クラウドフレア等を使っていれば特になくても大丈夫でした。引越し先で新たに証明書を取得するのでもいいのかもしれません。なんかあんまり覚えてないです。ごめんね〜。

.env.production

確かそのままコピーして持っていったはずです。キー情報とか記載してあるので必要なはず。

お引越し先で荷解き

データベース展開

以下のようなコマンドでお引越し先に展開します。
pg_restore -C -c -d mastodon_production バックアップファイル名

メディアデータ

お引越し元から先へ直接 scopy/rsyncを使ってれば楽かも。

SSL証明書

いい感じに。

.env.production

確かそのままコピーでいいはず。

住所変更

荷解きが終わったら、住所変更を申請します。具体的には使用しているDNSサーバに登録している(自ドメインの向き先)IPアドレスを変更します。反映までは多少時間がかかるようです。
前述のメンテナンス画面上で「お引越し元/先」がわかるようにしていればわかりやすいかも。

動作確認

向き先が変わったら、メンテナンス画面をオフ(もしくは自分だけ接続できるような設定にしておく)して、サービスに接続します。画像や動画投稿など、一通りの動作確認を行ってみたりします。

もし何らかの問題が起きていてすぐに解決しそうになければ、DNSの向き先を元に戻して引っ越しを一時中断、お引越し元を再開するなど考えたほうがいいかもしれません。

小まとめ

多分だいたいこんな感じで行けたはずです。何か漏らしてたらごめんなさい。

■チューニングのお話

公式ガイドなどを参考にチューニングしました。
インスタンスは登録者200人くらい、サーバはCPU:4コア8スレッド/メモリ:32GB程度の規模で、設定値を参考までに載せておきます。

データベースサーバ(Postgres)

PGTuneを使うと、postgresのパラメータを算出してくれますので、それを自分のサーバの設定に反映するとよいかと思います。

Postgres

各サービスのプロセス数、スレッド数の調整

Webサービス

同時に接続する利用者が多いならそれなりに確保する感じでしょうか。
執筆時点では4プロセス✕6スレッド、DB接続数(DB_POOL)は指定しなければWEB_CONCURRENCYの値になるらしいですが、なんか心配なので24にしてます。

mastodon-web.service
<省略>
Environment="WEB_CONCURRENCY=4"
Environment="MAX_THREADS=6"
Environment="DB_POOL=24"

Streamingサービス

デフォルトのままで良さそうです。

sidekiqサービス

設定がイマイチだとすぐに詰まったりするので、バランスが難しいかもです。1プロセスでスレッド数を増やしすぎても良くないらしく(sidekiq-wiki オプションの説明)、プロセス数を増やしてスレッド数は10までに抑える感じにしてます。
rubyはGVLで1スレッドしか同時に動けないとかなんとか(マルチスレッド/プロセスまとめ(Ruby編)

sidekiq

mastodon-sidekiq-default-1.service
<省略>
Environment="DB_POOL=12"
ExecStart=/home/xxxx/.rbenv/shims/bundle exec sidekiq -c 10 -q default

DB_POOL値はスレッド数+1以上が必要とこの記事で見たので、+2してます。

PgBouncer

データベースへの接続をプールして負荷を軽くしてくれる感じのやつです。公式ガイドでは接続数が100を超えるようなら導入をおすすめしている感じでした。

公式ガイドや導入記事を参考に真似して導入できました。うちでは導入後は接続数が15くらいに抑えられました。

公式ガイド
[mastodon] PgBouncerを導入する

開けるファイルの上限を増やす

特に「oo many open files」エラー等が出ていたわけじゃないですが、念の為に設定しました。
OS全体の設定を変えるより、各サービスごとに設定を変えるほうが安全とのことなので、各.service ファイルに以下を追記してあります。

LimitNOFILE=65536

unixドメインソケット

1サーバで運営しているなら、サーバ内の各サービス間の通信をTCPで行うよりはunixドメインソケットで行うほうが速いらしいので設定しました。
(勝手なイメージですが、同じ部屋にいる人と会話するのにわざわざ電話で会話するか直接会話するか、みたいな違いがあるのかなと思ってます。会話自体のスピードは変わらないけど、会話が始まるまでの手続きの時間が少なくなる感じ。違ったらごめん)

PostgresとRedisをunixドメインソケットで接続

この記事を参考にしました。

Mastodon 保守メモ

PgBouncerもunixドメインソケットで接続

postgresをunixドメインソケットにしたので、こっちも合わせて変更しました。

pgbouncer.ini
; listen_addr = 127.0.0.1
listen_port = 6432
unix_socket_dir = /var/run/postgresql

ローカルホスト接続は無しにして、ポート番号(これは必要っぽい)とディレクトリ名(postgresと同じ)で良いようです。

env.production
DB_HOST=/var/run/postgresql
DB_PORT=6432

Mastodonの環境設定ファイルも忘れずに変更しましょう。

Webサービス/Streamingサービスもunixドメインソケットで

公式ガイドには特に記載がなかったのですが(当時)、色々試したらできました。
.serveceファイルに以下の環境変数を追加します(指定するファイルの場所は任意でいいと思います)

mastodon-web.service
Environment="SOCKET=/tmp/mastodon.web.sock"
mastodon-streaming.service
Environment="SOCKET=/tmp/mastodon.stream.sock"

nginxの設定を変更して、"proxy_pass"に先程のunixドメインソケットを指定します。

example.com.conf
location @proxy {
    proxy_pass http://unix:/tmp/mastodon.web.sock;
}

location /api/v1/streaming {
    proxy_pass http://unix:/tmp/mastodon.stream.sock;
}

小まとめ

チューニング前に比べて、もっさりしたりsidekiqのキューが詰まったりすることが減ってきました。
現状は比較的スペックのよい物理サーバに乗せているということもあり、うちの規模のインスタンスなら余裕のよっちゃんです。

■カスタマイズ

公式ガイドでは、見た目のカスタマイズ、それを「テーマ」として設定する方法、ソースコードへのリンクを設定する方法が記載されてます。

見た目のカスタマイズ

見た目のカスタマイズはCSSをいじる感じになるので、お好みに合わせてゴリゴリやってください。
ここではうちのカスタマイズの中からおすすめなものをピックアップして紹介します。

ファボ★を別の絵文字に

kiritan.scss
/* ファボを肉球に */
.fa-star:before {
  font-size:large ;
  content: "\f1b0" ;
}

使える絵文字は Font awesomeで確認してみてください。うちでは肉球にしています。

未収載・非公開トゥートを色分け

kiritan.scss
/*非公開色分け*/
.status-private {
    background: rgba(180,55,132,0.2) ;
}

/*未収載色分け*/
.status-unlisted {
    background: rgba(36,190,56,0.2);
}

こんな感じです。
image.png

ユーザ絵文字・お知らせ欄

ユーザ絵文字とは、各アカウントのアイコンを絵文字のように扱えるやつです。:@user_name: でアカウント名を括ると絵文字になります。

image.png

お知らせ欄は、イベント告知などに便利です。

image.png

こちらの機能はbest-friends.chatに実装されているので、それをマージしてちょちょっと手直ししました。まだ、この機能の実装方法を解説できるレベルにないので紹介だけになります。

文字アニメーション

文字をぴょんぴょんさせたりびよんびよんさせたりする機能です。
ダウンロード.gif

(((文字)))[[[文字]]]{{{文字}}}等特定のカッコで括るとその部分がアニメーションする感じです。

CSSでアニメーションを定義する

yourcustom.scss
@keyframes rubberBand {
  from {
    transform: scale3d(1, 1, 1);
  }
  30% {
    transform: scale3d(1.25, 0.75, 1);
  }
  40% {
    transform: scale3d(0.75, 1.25, 1);
  }
  50% {
    transform: scale3d(1.15, 0.85, 1);
  }
  65% {
    transform: scale3d(0.95, 1.05, 1);
  }
  75% {
    transform: scale3d(1.05, 0.95, 1);
  }
  to {
    transform: scale3d(1, 1, 1);
  }
}

.rubberband{
  display: inline-block;
  animation: rubberBand 1.1s ease infinite;
}

びよんびよんはこんな感じ。
class="rubberband"がついた要素がアニメーションするようになります。
後はアニメーションさせたい文字をタグで囲んで、class="rubberband" を設定する感じです。

/app/javascript/mastodon/actions/importer/normalizer.js
// (((文字))) 3重カッコでくくられた箇所を抜き出し、クラスにrubberbandを設定する
const kiriAminefy = (text) => {
  var tmp_content = text;
  var match_result = tmp_content.match(/(\(\(\([^\)]+\)\)\))|(((([^]+))))/g);
  if (match_result && match_result.length > 0) {
      for (let p of match_result) {
          var replacement = `<span class="rubberband"><span>${p.slice(3, -3)}</span></span>`;
          tmp_content = tmp_content.replace(p, replacement);
      }
  }

export function normalizeStatus(status, normalOldStatus) {
// <省略>
    normalStatus.contentHtml  = kiriAminefy(emojify(normalStatus.content, emojiMap));
// <省略>

  return normalStatus;
}

詳細はソースコードを公開しているのでそちら を御覧ください。

未収載トゥートボタン/非公開トゥートボタン、簡易トゥートエリア(スマホ用) など

image.png

公開設定を選ばずに、これらのボタンで未収載/非公開のトゥートをワンアクションで行えます。

image.png

タイムラインから目を離すことなくトゥートを入力し、トゥートできます。
右利き・左利きどちらでも使いやすいようにトゥートボタンを左右に配置しています。

さて、時間がなくなってきてしまったので、ここらへんのカスタマイズのお話は別の機会に回したいと思います。

小まとめ

UIをいじろうとした時に、どういじっていいかわからず、しばらくの間はソースコードを眺めてるばかりでした。
そのうち、React+Reduxという枠組みで(フロント側は)作られているということを知って、ようやく勉強する取っ掛かりができた気がします。
別の機会に書くであろう記事ではその辺を整理しながら書き出せればいいなと思います。

まとめ

インスタンスを立ち上げて2年とちょっと経ちましたが、ようやく少しずつ弄ったりできるようになってきたかな、と思いました。もともとお勉強のために立ち上げたので、勉強ができてよかったです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした