🐘

Rocky Linux 9.1でMastodonサーバーの構築

2023/01/22に公開

この記事は何?

VPSのRocky Linux 9にMastodonをインストールして運用開始した作業の記録です。
整理しないまま2か月くらい経ってしまったので細かいところを忘れてそうで怖いですが、これ以上忘れないためにも書いておきます。

作業概要

  • OSはRocky Linux 9.1を使用します。
  • Dockerは使わず、ソースからインストールしていきます。
  • メディアの保存先としてAWS S3などのオブジェクトストレージは使いません。
  • この作業を行ったのは2022年11月20日頃です。
バージョン
Mastodon 4.0.2
nginx 1.20.1
PostgreSQL 13.7
Ruby 3.1.2

サーバーの環境と設定

サーバー

さくらのVPS 4Gプラン(SSD倍増オプション)

CPU 仮想4Core
メモリ 4GB
SSD 400GB

数人から数十人程度での利用を想定して選びました。
多くのフォロワーを抱えるアカウントがいるわけでもないので、十分すぎるくらいです。
https://vps.sakura.ad.jp/

OS

Rocky Linux 9.1(Blue Onyx)

デファクト・スタンダードなUbuntuを使わなかったのは、別の仕事でRocky Linux 9を使う予定があったので情報収集したかったのと、ちょっとした好奇心です。

パッケージのアップデート

基本的にはrootでの作業になります。
まずはパッケージを最新の状態にしておきましょう。

su -
dnf check-update
dnf -y update

スワップファイルの設定

さくらのVPSのRocky Linux 9の初期状態ではスワップファイルが設定されていませんでしたので、設定しておきます。

dd if=/dev/zero of=/swapfile bs=1M count=4096
mkswap /swapfile
chmod 600 /swapfile
swapon /swapfile

ちゃんと設定されたかどうかの確認をします。

swapon -s

再起動時にも有効になるようにしておきましょう。

/etc/fstab
/swapfile               swap                   swap    defaults        0 0

その他の基本設定

  • SSHやfirewalldなどの設定については、この記事では触れません。
  • ポートは80と443だけ空いていればOKです。
  • selinuxが有効になっていたら無効にしておいて下さい。

Mastdonの設定

ImageMagickとffmpegのインストール

PowerToolsレポジトリーがRocky Linux 9には存在しないため、以下のようにします。

dnf upgrade --refresh
dnf config-manager --set-enabled crb
dnf install epel-release
dnf config-manager --enable epel
dnf install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm
dnf install ImageMagick
dnf install ffmpeg ffmpeg-devel

※crbはいらなかったかも…

redisのインストール

dnf install redis

UNIXドメインソケットで接続した方がTCP接続より速くなります。

/etc/redis/redis.conf
unixsocket /run/redis/redis.sock
unixsocketperm 777

サービスの自動起動をオンにして起動します

systemctl enable -now redis

PostgreSQLのインストール

PostgreSQLのバージョンについては、試した限りでは13が一番素直に動いてくれた感じがしますが、私がPostgreSQLに慣れていないせいだったような気もします。

dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
dnf -qy module disable postgresql
dnf install -y postgresql13-server postgresql13-devel
export 'PGSETUP_INITDB_OPTIONS=--encoding=UTF-8 --no-locale';/usr/pgsql-13/bin/postgresql-13-setup initdb
systemctl enable --now postgresql-13
su - postgres
psql -c "alter user postgres with password '[任意のパスワード]'"
postgres=# CREATE USER mastodon CREATEDB;
postgres=# \q
exit

pg_hba.confの最後の方のidentをtrustに修正しておきます。
※これをやらないとmastodon-streamingがエラーを吐きます。

/var/lib/pgsql/13/data/pg_hba.conf
host    all             all             127.0.0.1/32            trust

pg_hba.confが見つからない場合は

su - posgres
psql
show hba_file

node.jsとyarnのインストール

curl -sL https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo
dnf install nodejs yarn

Mastodonのインストールに必要なパッケージのインストール

dnf install icu libicu-devel protobuf protobuf-compiler protobuf-devel libidn-devel postgresql-devel

rubyのインストール

rbenvを使ってrubyをインストールします。
ここで作ったユーザー'mastodon'のまま、この後しばらく作業します。

dnf install bzip2 gcc-c++ git {openssl,readline,zlib}-devel
dnf install perl
adduser mastodon
su - mastodon
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src && cd ~
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile && source ~/.bash_profile
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 3.1.2 && rbenv global $_ && rbenv rehash

Mastodon本体のインストール

gemを使ってMastodon本体をインストールしていきます。
Rubyになじみがないとかなり戸惑うところかも知れません。(戸惑った)

gem install bundler
git clone https://github.com/tootsuite/mastodon.git live && cd live
git checkout v4.0.2
gem install pg -- --with-pg-config=/usr/pgsql-13/bin/pg_config 
bundle config build.pg --with-pg-include=/usr/pgsql-13/include --with-pg-lib=/usr/pgsql-13/lib
bundle install --deployment --without development test

v4.0.2でなくとにかく最新のバージョンを入れたい場合は、git checkoutを以下のようにすると良さそうです。

git checkout $(git tag | tail -n 1)

秘密キーの作成

設定ファイルをコピーします。

cp .env.production.sample .env.production

以下のコマンドを3回実行して、出力されたキーをすべて保存しておきます

RAILS_ENV=production bundle exec rake secret

webpush用の秘密キーも作成して保存しておきます。こちらは2行出力されます。

RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key

保存しておいたキーを.env.productionに入力します。
最後の2行は、webpush用の秘密キーの2行です。

/home/mastodon/live/.env.production
LOCAL_DOMAIN=example.com
REDIS_URL=unix:///run/redis/redis.sock
DB_HOST= 
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=
DB_PORT=5432
PAPERCLIP_SECRET=[一つ目のキー]
SECRET_KEY_BASE=[二つ目のキー]
OTP_SECRET=[三つ目のキー]
S3_ENABLED=false

VAPID_PRIVATE_KEY=XXXXXXXXX
VAPID_PUBLIC_KEY=YYYYYYYYY

Elasticsearch

Elasticsearchは私のサーバーでは必要がなかったため無効にしました。

/home/mastodon/live/.env.production
ES_ENABLED=false

メールアドレスの設定

認証用メールに使うメールアドレスを設定します。
例えばgmailでしたらこんな感じになります。

/home/mastodon/live/.env.production
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_LOGIN=xxxxx@gmail.com
SMTP_PASSWORD= [Gmailのパスワード]
SMTP_FROM_ADDRESS=xxxxx@gmail.com
SMTP_DOMAIN=gmail.com

おひとりさまサーバーとして利用するならば、この設定は不要です。

データベースの作成

RAILS_ENV=production bundle exec rails db:setup SAFETY_ASSURED=1
RAILS_ENV=production NODE_OPTIONS=--openssl-legacy-provider bundle exec rails assets:precompile

ここまでの作業が済んだらrootユーザーに戻りましょう。

exit

起動ファイルの作成

用意されている雛形をコピーします。

cp /home/mastodon/live/dist/mastodon* /etc/systemd/system/

ウェブサーバー(nginx)の設定

nginx:80

nginxをインストールします。

dnf install nginx

SSL証明書取得用の設定をします。

mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
/etc/nginx/conf.d/example.com.conf
server {
  listen 80;
  server_name example.com;
  root /home/mastodon/live/public;

  location /.well-known {
    root /var/www/letsencrypt;
  }
}

サービスの自動起動をオンにして起動します

systemctl enable -now nginx

SSL(let's encrypt)

ここではgetsslを使ってlet's encryptの証明書を取得・更新する方法を紹介します。
getsslを置く場所は任意で。crontabで実行するのに都合の良い場所を選んで下さい。
(ここでは/rootに置いています。)

dnf install bind-utils
curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl
chmod 700 getssl
./getssl -c example.com

以下の行を修正します(※修正する行だけを表示しています)

/root/.getssl/getssl.cfg
CA="https://acme-v02.api.letsencrypt.org"
ACCOUNT_EMAIL="メッセージを取得するメールアドレス"
AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
/root/.getssl/example.com/getssl.cfg
CA="https://acme-v02.api.letsencrypt.org"
ACL=('/var/www/letsencrypt/.well-known/acme-challenge')

証明書を取得します。更新する場合も同じです。

./getssl example.com

cronで自動更新できるようにしておきましょう。
実行の頻度やログの出力先は任意で。

crontab -e
0 6 * * 1 /root/getssl example.com >> /home/admin/logs/getssl.log
30 6 * * 1 systemctl reload nginx >> /home/admin/logs/getssl.log

※毎週月曜日の午前6時に実行、30分後にnginxをリロード

nginx:443

/home/mastodon/live/dist/nginx.confをコピーして、server_nameと証明書周辺を修正します。
let's encryptの自動更新のため80ポートの.well-knownのところも修正しておきましょう。

/etc/nginx/conf.d/example.com.conf
server {
  listen 80;
  ...
  location /.well-known {
    root /var/www/letsencrypt;
  }
  ...
}
server {
  listen 443;
  ...
  server_name example.com;
  ...
  ssl_certificate /root/.getssl/example.com/fullchain.crt;
  ssl_certificate_key /root/.getssl/example.com/example.com.key;
  ...
}

nginxの実行ユーザーをmastodonに変更します。

/etc/nginx/nginx.conf
#user nginx;
user mastodon;
chown -R mastodon:mastodon /var/lib/nginx
systemctl restart nginx

Mastodonの起動

4つのサービスをまとめて起動します。

systemctl enable /etc/systemd/system/mastodon-*.service

お疲れ様でした。

おまけ

PostgreSQLのチューニング

PGTuneなどを参考にPosgtgreSQLの設定を最適化した方が良いです。
https://pgtune.leopard.in.ua/

SideKiqのチューニング

プロセスの数や優先度をかなり柔軟に設定できます。
私はschedulerを別プロセスに分離しましたが、処理が集中しやすいdefaultを分離する方が王道かも知れません。

/etc/systemd/system/mastodon-sidekiq
bundle exec sidekiq -c 25 -q default,4 -q ingress,2 -q push,2 -q pull -q mailers
/etc/systemd/system/mastodon-scheduler
bundle exec sidekiq -c 10 -q scheduler

ストレージ

S3を使わないことにしたので、そのかわりにCDNで本体サーバーへの負荷を軽減しました。
「さくらのクラウド」のウェブアクセラレータを使ってます。

/home/mastodon/live/.env.production
CDN_HOST=https://xxxxx.user.webaccel.jp

また、ストレージの節約のために保存する画像のサイズを変更しました。

/home/mastodon/live/app/models/media_attachment.rb
-pixels: 2_073_600,  # 1920x1080px
+pixels: 640_000, # 800x800px
--quality 90
+-quality 80

nginxのチューニング

あまり手を入れてないのですが、接続数や開けるファイル数あたりは大きくしておいた方が良いかもです。

worker_processes auto;
worker_rlimit_nofile 10000;

events {
    worker_connections 4096;
}

基本的な管理操作

アカウント登録

ユーザーxxxをメールアドレスxxx@mail.comで登録したい時は

su - mastodon
RAILS_ENV=production bundle exec bin/tootctl accounts create xxx --email=xxx@mail.com
(PASSWORDが出力される)

メール確認完了

RAILS_ENV=production bundle exec bin/tootctl accounts modify xxx --confirm

権限追加

ユーザーxxxに権限Adminを追加したい時は

RAILS_ENV=production bundle exec bin/tootctl accounts modify xxx --role Admin

参考にしたサイト(ありがとうございました!)

https://kyohju.com/article/post-1393.html
https://bmw-and-more.info/2020061301
https://zenn.dev/yakumo/articles/aa0a569402b94d398707fe64ae90982b

Discussion