ふえんわーくすらいふろぐ

Fuen-Works(https://fuen-works.tokyo/)の管理人のまとめ。 アニメ、IT関係、日々考えてることだったりをテキトーに書いてます。

さくらVPS+CentOS7でMastodonサーバを構築してみた、リトライ(Dockerなし)。


43

今回構築したサーバ、クロサワドン!サンシャイン!!


9月末からMastodonのサーバ構築をやってました。

以前書いた通り、5月に一度構築を実施したのですが...。
9月中にバージョン1.3.3→1.6.0にアップさせようとした際、間違えてDBの中身を全消ししてしまい、バージョンアップに失敗してしまいました。
んー、じゃあせっかくだし再構築しようか!と思い立ち、一から構築し直す事にしました。


なぜかといえば、理由は2つ。

ひとつは、最初はDockerを使って構築したのですが、それだと万が一「DBだけ外出ししたいなぁ...」とか考えたときに、構成を変えるのがめんどくさそうだったから。

もうひとつは、もうDockerを使っての構築は一度やったし、ネット上を探すとたいていDockerを使った方法で書かれてたからです。

せっかくなら、Dockerなしでの構築に挑戦してみたい。
まぁ、そんな気持ちが後々の苦労を呼んだわけですが。



今回は、本当に一から手順を細かく書いていきたいと思います。
バージョンは構築時点で最新だったVer.1.6.1で進めます。

基本は、下記2つのサイトにしたがって実施しました。
ただし、2.はDockerありでの構築方法なので、参考程度に。

1. 
CentOS7.3にMastodonの構築(Dockerなし)
2. さくらの VPS + CentOS7 で 俺専用 Mastodon インスタンスを立ててみた話



【さくらVPS仮想マシンの払い出し】

書くまでもないですが、さくらのVPS仮想マシンの払い出しをします。
今回は最小スペックの512MBです。
ただ、実際使っているとコンパイルに失敗する回数がかなり多いので、1GBのほうがいいかもしれません。



【お名前.comでドメインの払い出し】

これも書くまでもないですが、お名前.comでドメインの払い出しをします。
安いからという理由で払い出した「.xyz」ドメインのアドレスを引き続き使います。



【OSインストール】

さくらVPSのコンソールにて、OSを選択しインストールします。
今回は「カスタムOS」のCentOS7を選びました。
まったくいじられてないCentOS7だとちょっと不安だったので。

CentOS7の「Software Selection」は、「Basic Web Server」を選択。
まぁ、MastodonはWebサーバだろうし、という安直な理由。

お約束のadminのパスワード設定、ユーザの追加、パスワードの設定も実施。



インストール完了後、わたしはさらにMastodonインストール用のユーザを追加しました。
useradd mastodon
passed mastodon


で、sudo可能ユーザの追加を実施します。
username ALL=(ALL) ALL

以降、特に必要に迫られない限り、mastodonユーザで実行します。



CentOSの初期設定】

続いて、CentOSとしての初期設定をやっていきます。

まずは、ホスト名の変更。
現在の設定を確認したのち、変更したいホスト名に変更します。
hostname
hostname kurosawa-ruby.xyz


次に、firewalldの設定をします。

まずはfirewalldのインストール
yum install firewalld systemctl start firewalld.service systemctl enable firewalld.service

インストール後、穴を開けるためのコマンド実行。
実行後のリロードも忘れずに。
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=xxxxx/tcp
firewall-cmd --permanent --add-port=5432/tcp
firewall-cmd --permanent --add-port=6379/tcp
firewall-cmd —-reload

※xxxxxポートは、後ほどSSH接続するためのポート番号です。飛ばしても問題なし。
※5432ポートは、PostgreSQLのポート、6379はRedisのポートです。



ファイヤーウォールの設定が終わったら、SSH関連の設定をします。
cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config.bkYYYYMMDD
vi /etc/ssh/sshd_config

まず、SSHポート番号を変更します。

デフォルトではポート番号22になってるSSHのポートを他の番号へ変更します。
これをやるだけでSSHでの不正アクセスがほぼなくなります。

変更前:
Port 22
変更後:
#Port 22
Port xxxxxx

新ポートは、DYNAMIC AND/OR PRIVATE PORTSである、49152〜65535番から選びました。

※セキュリティの都合上、場号は秘密です。


続いて、直接rootでログインするのを禁止します。

変更前:
PermitRootLogin yes
変更後:
#PermitRootLogin yes
PermitRootLogin no


ここまで変更して、SSHを再起動します。
systemctl restart sshd


SSH関連の設定が終わったら、サーバ時刻の調整をします。
サーバの時刻がズレてないか確認し、ズレがあったら「ntpdate」で修正。
date
/usr/sbin/ntpdate -v ntp.nict.jp 1>>/home/user/log/cron.log 2>>/home/user/log/err.log


まだいきます。

続いて、wgetのインストール。
yum -y install wget

グループインストール機能のインストール。
yum -y groupinstall base

zlib(zipファイルの読み書き)機能のインストール。
yum -y install zlib-devel

realine機能(行頭・行末移動、ヒストリ機能他)のインストール。
yum install -y readline-devel


一旦、ここまででアップデート確認。
yum update


ここまでがCentOS7の初期設定。
ここから、Mastodon構築の準備に入ります。



Mastodon構築(インストール編)】

しつこいようですが、Ver.1.6.1の前提で進めます。

まずは必要なパッケージのインストール。
依存関係があるパッケージをまとめてインストール。
sudo yum install libxml2-devel ImageMagick libxslt-devel git curl file g++ protobuf-compiler protobuf-devel

リポジトリのインストール。
sudo yum -y install epel-release
sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

FFmpegインストール。

FFmpegは、動画や音声を再生するためのツール。
初めて知った。
sudo yum -y install ffmpeg ffmpeg-devel

開発ツールインストール。
sudo yum group install "Development tools"
sudo yum -y install ffmpeg ffmpeg-devel

Node.jsインストール。

今回はACTIVE LTS=長期サポート対象期間のものが欲しかったので、6.x系にしました。
安定的に動いてるのが欲しいし。
curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
sudo yum install nodejs


yarnインストール。

yarnとは、FacebookとExponent、Google、Tildeとの共同チームによって生まれた新しいパッケージマネージャー...とのこと。
初めて知りました。

参考:yarnを使ってみた
sudo npm install -g yarn

Redisインストール。

Redisは、高速なオンメモリデータベースとのこと。
これも初めて知りました。
なお、「レディース」と読むらしい。
sudo yum install redis rubygem-redis

PostgreSQLインストール。

合わせて、DBユーザの作成もやってしまいます。
sudo yum install postgresql-server postgresql postgresql-contrib postgresql-devel sudo postgresql-setup initdb sudo systemctl start postgresql sudo systemctl enable postgresql sudo -u postgres psql postgres=# CREATE USER mastodon CREATEDB; postgres=# \q


rbenvインストール。
git clone https://github.com/rbenv/rbenv.git ~/.rbenv cd ~/.rbenv && src/configure && make -C src echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile source ~/.bash_profile git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build sudo yum install openssl-devel readline-devel rbenv install 2.4.1 rbenv global 2.4.1


ここでハマりポイント、その1。

最初インストールを実施した時、rubyのバージョンが切り替わらなくて、ここで詰まりました。
どうやら、rbenv実行場所が間違ってたようです。


最後に、このコマンドで完了。
rbenv rehash


nginxインストール。
yum install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm yum -y install --enablerepo=nginx nginx systemctl start nginx systemctl enable nginx


Mastodonのインストール。

考えてみたら当たり前の話ですが、これはmastodonユーザで実行してください。
※下記、ハマりポイント、その2を参照。


依存関係のインストール
gem install bundler
bundle install --deployment --without development test
yarn install --pure-lockfile


ハマりポイント、その2。

bundle installを実行しようとして、command not foundになりました。
/opt以下にmastodnをgit cloneしたのですが、これをsudoで実行したことで所有者/グループがrootになってました。
そのことでpermission denidされていたようです。

参考:sudo実行時に$PATHが通っていない場合の設定

なので、mastodonユーザに切り替えて、git cloneし直しました。


ハマりポイント、その3。

あらためてbundle installしようとしたところ、gem install charlock_holmes -v ‘0.7.5’しろとエラーが出ました。
というわけで、
gem install charlock_holmes -v '0.7.5'

今度は、brew install icu4c or apt-get install libicu-devしろとエラーが出ました。
しかし、この時点ではLinuxbrewは入ってませんでした。

というわけで、Linuxbrewインストール。
Linuxbrewとは、macOSで使えるパッケージ管理システム、HomebrewのLinux版。
ちなみに、Linuxbrewインストールはこのハマりポイントにかかわわらず、どっちにしても必須です。
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install)" echo 'export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"' >>~/.bash_profile
echo 'export MANPATH="/home/linuxbrew/.linuxbrew/share/man:$MANPATH"' >>~/.bash_profile
echo 'export INFOPATH="/home/linuxbrew/.linuxbrew/share/info:$INFOPATH"' >>~/.bash_profile PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
brew install gcc
参考:Linuxbrew

で、あらためて実行。
brew install icu4c

これは無事完了。

再度、bundle installを実行するも、今度はgem install idn-ruby -v ‘0.1.0’しろとエラー。
そこで、このコマンドを実行。
gem install idn-ruby -v '0.1.0'

ところが、「ERROR: could not find idn library!」というエラーメッセージ。
調べたところ、このコマンドを実行しろってことらしい。
yum install -y libidn-devel

特に問題なく、コマンドは実行完了。

再度、コマンド実行。
gem install idn-ruby -v '0.1.0'

ところが、「ERROR: could not find idn library!」と、同じエラーメッセージが出た。
ここは本当に詰まってあれこれ調べたものの、どうやらCentOSのlibidnでインストールできるライブラリと、必要としているバージョンの不一致のようなメッセージが出ました。
で、迷った挙句、bundlerのバージョンを落とすことにしました。
構築時の最新は1.15.xでしたが、1.14.6を使用することに。
gem install bundler -v "1.14.6"

これは問題なくインストールできました。



Mastodon構築(設定編)】

さて、ここからは各種設定に入っていきます。

先ほどインストール完了したbundlerのコマンドを実行していきます。
基本的な実行場所は、mastodonをcloneした「/opt/mastodon」です。


さっそく、ハマりポイント、その4。

bundle exec rakeが「NameError: uninitialized constant Annotate」で実行できない。
これは今回参考にしたページにも書かれていて、下記ページを参考にしました。
下の方の会話の中で解法が出てきます。

参考:
Mastodonインストール時に"rake secret"でエラーが発生する 

それに従い、「RAILS_ENV=production」をつけ、実行します。
RAILS_ENV=production bundle exec rake secret RAILS_ENV=production bundle exec rake secret RAILS_ENV=production bundle exec rake secret

これで実行できました。


次は、nginxのconf作成。
vi /etc/nginx/conf.d/kurosawa-ruby.xyz.conf

もともと使ってたconfとマージ。
特にSSL関連を重点的に内容を追加。
下記のgithubのページの下の方に「nginx Configuration」が書かれてますので、それを参考に。

そしてnginxの起動&自動起動の設定。
systemctl restart nginx systemctl enable nginx


次は、Let's Encryptのセッティング。

Let's Encryptは無料で使えるサーバ証明書です。
詳細はGoogle先生に聞いてください。
cd /opt
git clone https://github.com/certbot/certbot
cd /opt/certbot
./certbot-auto certonly --standalone -d kurosawa-ruby.xyz


OpenSSLのDiffie-Hellmanパラメータを生成する。
mkdir /etc/nginx/ssl cd /etc/nginx/ssl openssl dhparam 2048 -out dhparam.pem

Diffie-Hellman鍵交換プロトコルを指定、鍵長を2048bitに指定

opensslコマンドは多数のオプションが存在するようです。



メールの設定...は、今回はそのまま流用したので、何もしていません。
新規の場合は、下記を参考にしてください。
わたしは.xyzドメインを使用している都合上、SendGridを使っています。

参考:MastodonのメールサーバにSendGridを使う際のポイント


ここまできたら、いよいよMastodonのセットアップ。

コンパイルとサービスの登録をしていきます。
サービスの記述内容は、最初の参考のページをみてください。
cd /opt/mastodon
RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile

sudo vi /etc/systemd/system/mastodon-web.service
sudo vi /etc/systemd/system/mastodon-sidekiq.service
sudo vi /etc/systemd/system/mastodon-streaming.service

sudo systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
sudo systemctl enable /etc/systemd/system/mastodon-*.service

ここでハマりポイント、その5。

mastodon-web.service、mastodon-streaming.serviceが起動しない。
で、あれこれ試行錯誤した結果、.serviceに記述した下記が問題だった。
WorkingDirectory=/home/mastodon/live

参考にしたページでは、上記パスにMastodonを入れてたので問題なかったのですが、わたしの場合はここまで「/opt/mastodon」に入れてきました。
ここだけ見落としてしまったようです。
そこで、下記に設定を変更しました。
WorkingDirectory=/opt/mastodon

再度コマンド実行して、起動完了。

ここまでやると、取得したドメインにアクセスするとMastodonの画面が表示されます。
設定がうまくできて入れば、アカウント登録と指定したメールアドレス宛のメールが飛ぶはずです。


アカウント登録後、admin設定をします。
RAILS_ENV=production rails mastodon:make_admin USERNAME=xxxxx(アカウントのID)


最後に、cronの設定をします。
0 5 1 * * reboot 1>>/home/daiyak/log/cron.log 2>>/home/daiyak/log/err.log 0 1 * * * /usr/sbin/ntpdate -v ntp.nict.jp 1>>/home/daiyak/log/cron.log 2>>/home/daiyak/log/err.log 0 2 * * * yum update -y 1>>/home/daiyak/log/cron.log 2>>/home/daiyak/log/err.log 0 3 */7 * * systemctl stop nginx && /opt/certbot/letsencrypt-auto renew --force-renew && systemctl start nginx 1>>/home/daiyak/cron.log 2>>/home/daiyak/err.log # 0 4 * * * echo "" >> /home/marutodon/log/mastodon/daily.log && cd /opt/mastodon && date >> /home/marutodon/log/mastodon/daily.log && /opt/mastodon/RAILS_ENV=production bundle exec rake mastodon:daily >> /home/marutodon/log/mastodon/daily.log 2>&1 30 4 * * 0 echo "" >> /home/marutodon/log/mastodon/remove_remote.log && cd /opt/mastodon && date >> /home/marutodon/log/mastodon/remove_remote.log && /opt/mastodon/RAILS_ENV=production bundle exec rake mastodon:media:remove_remote >> /home/marutodon/log/mastodon/remove_remote.log 2>&1

順番に説明します。

1つめは、サーバ再起動のコマンドです。
2つめは、ntpdateコマンドによる時刻合わせのコマンドです。
3つめは、yumのupdateのコマンドです。今回は自動でアップデートするようにしました。
4つめは、Let's Encryptの自動更新のためのコマンドです。Let's Encryptの公式に書かれてたような気がします。
5つめ、6つめはMastodonの毎日実行するジョブです。

下記ページを参考にしました。

参考:マストドン運営に必要なデイリータスクとキャッシュ削除タスクを cron ジョブに登録する



とまぁ、こんな風に構築をやっていって、確か1週間強くらいかかったような気がします。

特に、ハマりポイント、その3のライブラリのバージョンの不一致のところは本当に苦労して、ここだけで3日か4日ぐらいハマってたような気がします。
そのあたり、うまいこと調整してくれるDockerの恩恵がすごい大きかったんだな、と感じました。。。

まぁ、このあとはまたカスタマイズでまた苦労することになるのですが...それはまた次回。