🐘

Mastodonお一人様サーバ構築メモ

2023/01/20に公開

Mastodon のサーバをVPSにシングルユーザモードで構築したので手順をメモ。
基本的には公式のガイド(下記)に従って進めた。
https://docs.joinmastodon.org/admin/install/
作業は M1 MacBookAir 上で実施した。Docker は使用していない。

基本情報

サーバ

KAGOYA CLOUD VPS 2コア/2GB/25GB
https://www.kagoya.jp/
もう少しスペックが低くてもよさそうだが、サーバ上でいろいろ他の作業もするかもしれなかったので余裕を持たせた。

ドメイン

さくらのドメインで契約中のドメインに、本サーバ用のサブドメインをぶらさげている。
本記事では sub.example.com とする。

OS

Ubuntu 20.04 (公式のおすすめに従った)

メディアファイル保存先 (S3)

画像等のメディアファイルは AWS S3 に保存したかったのであらかじめ S3 にバケットを作っておいた。設定等は以下の通りだが、試行錯誤しながらのためこれがベストかどうかは不明。
バケットポリシーはこんな感じ。バケット名は sub-example-com 、S3アクセス用にIAMユーザ s3user を用意した。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::xxxxxx:user/yamako",
                    "arn:aws:iam::xxxxxx:user/s3user"
                ]
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::sub-example-com",
                "arn:aws:s3:::sub-example-com/*"
            ]
        }
    ]
}

また、Cross-Origin Resource Sharing (CORS) に以下を設定している。

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

ブロックパブリックアクセスは以下の2つをオンにしている。

  • 新しいパブリックバケットポリシーまたはアクセスポイントポリシーを介して付与されたバケットとオブジェクトへのパブリックアクセスをブロックする
  • 任意のパブリックバケットポリシーまたはアクセスポイントポリシーを介したバケットとオブジェクトへのパブリックアクセスとクロスアカウントアクセスをブロックする

オブジェクト所有者 は ACL 有効, 希望するバケット所有者 を選択。

構築時の手順

サーバを作る

VPSを契約したら、KAGOYA CLOUD のコントロールパネルからインスタンスを作成し、サーバを立ち上げる。SSH秘密鍵である「ログイン用認証キー」はなくさないように保存しつつ、作業するMac にコピーしておく。

cp /path/to/ログイン認証キーのファイル名 ~/.ssh
chmod 600 ~/.ssh/ログイン認証キーのファイル名

~/.ssh/config に以下を記述する。servername は適当な文字列で。

Host servername
  HostName サーバのIPアドレス
  User root
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/ログイン認証キーのファイル名

以下でサーバに接続する。

ssh servername

DNS設定

さくらのドメインの設定画面から sub.example.com の A レコードを作成する。IPアドレスはサーバのものを設定。
メディアファイルをプロキシする用に files.sub.example.com の A レコードも作成しておく(IPアドレスは sub.example.com と同じ)。
PTRレコードを KAGOYA CLOUD 側で設定する。PTRレコードがないと、メールがスパム扱いにされたりいろいろ残念なことが起きた経験があるので設定しておいた。

メール設定(Mailgun)

シングルユーザモードなのでメール配送の設定はなくてもよかったかもしれないが、興味があったので設定した。
メールサービスは mailgun.com を利用した。
無料で 5000 通まで配送できるが、クレジットカード登録したうえで free プランへの登録が必要。

クイックスタートガイドに従って設定する。
https://documentation.mailgun.com/en/latest/quickstart-sending.html#how-to-start-sending-email
ドメインを登録するとTXT,CNAME,MXレコードを設定するよういわれるので、さくらのドメインコントロールパネルから設定する。

はまったポイント

  • データ部分のスペースに改行が入っていることがあるので消す
  • データ部分にドメインを入れるときは末尾に . をつける
  • MXレコードのデータ部分は 10 hostname のようにまとめて書ける
  • 途中、テストメールを送るステップがあるが、迷惑メールに入るので注意

サーバに必要なソフトウェアをインストール

ssh servername して root で実行していく。このあたりは joinmastodon.org にある通り。

update

apt update && apt upgrade -y

fail2ban

apt install fail2ban
vi /etc/fail2ban/jail.local
systemctl restart fail2ban

iptables-persistent

apt install -y iptables-persistent
vi /etc/iptables/rules.v4
vi /etc/iptables/rules.v6

証明書系

apt install -y curl wget gnupg apt-transport-https lsb-release ca-certificates

Node.js

curl -sL https://deb.nodesource.com/setup_16.x | bash -

PostgreSQL

wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list

色々インストール

apt update
apt install -y \
  imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core \
  g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf \
  bison build-essential libssl-dev libyaml-dev libreadline6-dev \
  zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev \
  nginx redis-server redis-tools postgresql postgresql-contrib \
  certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev

certbot については joinmastodon.org にある手順は古いので公式の手順に従ったほうがいいという話も聞いたのでご参考までに。
https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal
2023/6/20追記: 公式の手順に従うと、後述の証明書の自動更新も設定済みになるという話も。

yarn

corepack enable
yarn set version classic

Ruby

rbenv で管理する。まずユーザをつくって

adduser --disabled-login mastodon
su - mastodon

rbenvをいれて

git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec bash
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

ターゲットのRubyをいれる

RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4
rbenv global 3.0.4

Bundlerもいれる

gem install bundler --no-document

いったん抜ける

exit

ここまででインストール終わり。

DBセットアップ

pgTune で最適な postgresql.conf を作る。

# DB Version: 15
# OS Type: linux
# DB Type: web
# Total Memory (RAM): 2 GB
# CPUs num: 2
# Data Storage: ssd

max_connections = 200
shared_buffers = 512MB
effective_cache_size = 1536MB
maintenance_work_mem = 128MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 1310kB
min_wal_size = 1GB
max_wal_size = 4GB

サーバ上にある設定ファイルを上記の内容で書き換えて、restart

vi /etc/postgresql/15/main/postgresql.conf
systemctl restart postgresql

DBに必要なユーザを作成しておく。

sudo -u postgres psql
CREATE USER mastodon CREATEDB;
¥q

Mastodonセットアップ

Github から clone して、最新版の tag に切り替える。

su - mastodon
git clone https://github.com/mastodon/mastodon.git live && cd live
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

Note: switching to 'v4.0.2'. とのことで、最新になった。

必要なパッケージをいれていく。

bundle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN)
yarn install --pure-lockfile

インストレーションウィザードがあるので実行する。

RAILS_ENV=production bundle exec rake mastodon:setup

こんなかんじで実行した。
シングルユーザモードだとadmin 兼 最初のユーザもここで作成できるが、メール経由で認証を行う必要もあった。メール認証をスキップする方法があるかもしれない(あってほしい)。

Your instance is identified by its domain name. Changing it afterward will break things.
Domain name: sub.example.com

Single user mode disables registrations and redirects the landing page to your public profile.
Do you want to enable single user mode? yes

Are you using Docker to run Mastodon? no

PostgreSQL host: /var/run/postgresql
PostgreSQL port: 5432
Name of PostgreSQL database: mastodon_production
Name of PostgreSQL user: mastodon
Password of PostgreSQL user:
Database configuration works! 🎆

Redis host: localhost
Redis port: 6379
Redis password:
Redis configuration works! 🎆

Do you want to store uploaded files on the cloud? yes
Provider Amazon S3
S3 bucket name: sub-example-com
S3 region: ap-noutheast-1
S3 hostname: s3-ap-noutheast-1.amazonaws.com
S3 access key: S3のアクセスキー
S3 secret key: S3のシークレットキー
Do you want to access the uploaded files from your own domain? Yes
Domain for uploaded files: files.sub.example.com

Do you want to send e-mails from localhost? No
SMTP server: smtp.mailgun.org
SMTP port: 587
SMTP username: mastodon@sub.example.com
SMTP password:
SMTP authentication: plain
SMTP OpenSSL verify mode: none
Enable STARTTLS: auto
E-mail address to send e-mails "from": Mastodon <notifications@sub.example.com>
Send a test e-mail with this configuration right now? Yes
Send test e-mail to: 自分のメールアドレス
E-mail could not be sent with this configuration, try again.
SMTP-AUTH requested but missing secret phrase
Try again? no

This configuration will be written to .env.production
Save configuration? Yes

Now that configuration is saved, the database schema must be loaded.
If the database already exists, this will erase its contents.
Prepare the database now? Yes

メールの送信テストでエラーが出たので、以下を参考に .env.production の SMTP_AUTH_METHODSMTP_OPENSSL_VERIFY_MODE をコメントアウトした。
https://stackoverflow.com/questions/49567479/smtp-mailgun-throwing-error-with-mastodon

rootにもどる。

exit

nginx セットアップ

あらかじめ用意されている設定ファイルのテンプレートをコピー

cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon

example.com を自分のサーバのドメイン sub.example.com に書き換えて、ssl_certificate のコメントを外す。

vi /etc/nginx/sites-available/mastodon

で、再起動…だが失敗する。

systemctl reload nginx

ssl_certificate で設定している Let's Encrypt の証明書がないためだった。
nginxをいったんとめて、証明書を発行してから起動すればOKだった。
この辺はもっといいやり方がありそうに思う。

systemctl stop nginx
certbot certonly --standalone -d sub.example.com
systemctl start nginx

systemd セットアップ

設定ファイルをコピー

cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/

中のパスとかまちがってないか軽くチェック

vi /etc/systemd/system/mastodon-*

Mastodon サーバ起動

ここまできたら Mastodon サーバを起動する。

systemctl daemon-reload
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming

起動後、ブラウザでアクセスして、Mastodonのメニューが出れば成功!

https://sub.example.com/@yamako

nginx で S3 の proxy する設定

公式に手順があるのでそのとおりに実施。
https://docs.joinmastodon.org/admin/optional/object-storage-proxy/
ただ、nginxのconfigを編集するだけではなく SSL の設定も必要。
nginx を停止してから、証明書を追加。

systemctl stop nginx
certbot certonly --standalone -d files.sub.example.com
systemctl start nginx

エラーログを見るには

journalctl -u mastodon-sidekiq --no-pager

などとする。

証明書の自動更新について

certbot で発行したSSL証明書には期限があるので、定期的に延長するコマンドを動かす必要がある。
2023/6/20追記: certbot公式の手順でインストールするとこの設定は不要かもしれない。

以下は cron で朝3:00に更新する例。pre-hook で nginx を停めて、post-hook で起動する。

0 0 3 * * certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"

certbot をインストールするとあわせて証明書を自動更新してくれる証明書の状態を確認してくれる certbot.timer が入る。以下で動作状況を確認できる。証明書の更新まではされない。

# systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Wed 2023-01-18 14:27:55 JST; 1 weeks 1 days ago
    Trigger: Fri 2023-01-27 04:42:08 JST; 10h left
   Triggers: ● certbot.service

参考

更新履歴

  • 2023/6/20: 証明書の自動更新をcronで行う方法について追記しました。またcertbot.timerの説明が誤っていたので修正しました。certbotインストール時の注釈も追記しました。
  • 2023/1/26: 証明書の自動更新について追記しました。
  • 2024/2/21: スパム対策について追記しました。

Discussion