Mastodonを「お一人様インスタンス1」で運用して気になることの一つに、「もっと消費メモリを圧縮できないかな……」ということがあると思います。
そこでPhusion Passenger2。
Mastodonを立ち上げる際の選択肢として言及はされているものの、その方法自体は見掛けない気がするこのPassengerに載せ替えてみたところ、どうやら良い感じになりました。
以下は私が実際に運用している「お一人様インスタンス」で、負荷に応じてPassengerが適当にWorkerを増減させてくれている様子(が見える消費メモリの推移)です。
メモリ1GBの手軽なVPSでも心の余裕がうまれるグラフです:-)
この構成では結局Mastodonだけでサーバを占有している状態ですが、他のアプリケーションなどと同居させる場合に威力を発揮しそうです。
この記事では、Production guideに従った環境、すなわちDockerを利用していない、mastodon-web
及びmastodon-streaming
をPassenger(+nginx)に置き換える方法を扱います。
Mastodonの立ち上げ方そのものについては、先達が沢山いらっしゃるのでそちらが参考になると思います。
前提条件
- Production guide(a3097c9)に準拠する形でCentOS7.3上に構築3、利用可能な状態のMastodon(v1.3.3)を出発点にしています
- 以降の手順のコマンドは、全て
mastodon
ユーザとして実行します- 設定ファイルの編集コマンド等は省略しています
既にPassengerの準備ができている場合
以下の項目がお役に立つかも知れません
Passengerインストール
Installing Passenger + Nginx on Red Hat 7 / CentOS 7 (with RPM) - Passenger Libraryといった手順がありますが、この方法では異なるバージョンのRubyが不必要にインストールされてしまったり、ChromeでHTTP/2が有効にならなかったりします。
Production guideに従うとrbenvを持ったmastodonユーザーがいるはずですので、今回はこれを利用してGemインストール+ビルド、という手段をとることにします。
gemインストール
gemを利用してpassengerをインストールします。
cd ~/live
gem install passenger --no-ri --no-rdoc
ソースコード準備
ビルドに利用するnginx、opensslのソースコードを用意します。
- nginxのバージョンは、Passenger5.1.3から1.10.3が推奨されていますので、それ以降が良いと思います
- HTTP/2(ALPN)に対応するには、opensslのバージョンは1.0.2以上が必要です
cd /usr/local/src
curl -L -O https://nginx.org/download/nginx-1.12.0.tar.gz
sudo tar xofz nginx-1.12.0.tar.gz
curl -L -O https://www.openssl.org/source/openssl-1.1.0e.tar.gz
sudo tar xofz openssl-1.1.0e.tar.gz
ビルド用パッケージ準備
libcurl-devel
をインストールします。
他のディストリビューションの場合、読み替えて同等のパッケージを導入してください。
sudo yum install -y libcurl-devel
ビルド
以下のコマンドを実行してビルドします。
この環境では単純にsudoしてgemインストールしたコマンドを利用することはできないため、冗長な形になっています。
また、環境に応じて次の箇所を適宜修正した上で実行してください。
-
versions/2.4.1
rbenvでインストールしたRubyのバージョン -
passenger-5.1.3
gemでインストールしたPassengerのバージョン -
--prefix=/opt/nginx
これからビルドするnginxのインストール先 -
--nginx-source-dir
nginxのソースコードの場所 -
--with-openssl
opensslのソースコードの場所
sudo PATH=/home/mastodon/.rbenv/versions/2.4.1/bin:$PATH \
/home/mastodon/.rbenv/versions/2.4.1/bin/ruby \
/home/mastodon/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/passenger-5.1.3/bin/passenger-install-nginx-module --auto \
--prefix=/opt/nginx \
--nginx-source-dir=/usr/local/src/nginx-1.12.0 \
--extra-configure-flags="--with-ipv6 --with-openssl='/usr/local/src/openssl-1.1.0e'"
それなりに時間が掛かるので待ちます。
正常終了するとNginx with Passenger support was successfully installed.
と表示されます。
設定ファイルを準備
既存のnginxから設定を適宜移行します。
上記の手順でnginxをインストールした場合、デフォルトで読み込まれる設定ファイルがconf
ディレクトリ下になっていることに注意してください。
一通り移行したところで、設定に誤りが無いことを確認しておきます。
sudo /opt/nginx/sbin/nginx -t
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
systemd対応
NGINX systemd service file | NGINXを参考にファイルを作成し、今回インストールしたnginxをsystemctl
で操作できるようにします。
環境に応じて、PIDFile
の場所及び/opt/nginx
を適宜修正してください。
また、PrivateTmp
をtrue
とすると、そのままでは「Passenger Instance Registry」を取得することが難しくなり後々困るため、ここではfalse
にしておきます。
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/opt/nginx/sbin/nginx -t
ExecStart=/opt/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=false
[Install]
WantedBy=multi-user.target
Passengerで動作させるためのアプリケーション準備
babel-node
→ node
Passengerではbabel-node
相当の機能が無さそうなため、事前にビルドする必要があります。
package.json
のscripts
内にbuild
を追記します。
{
...
"scripts": {
...
"start": "babel-node ./streaming/index.js --presets es2015,stage-2",
"build": "babel streaming -d build --presets es2015,stage-2",
"storybook": "start-storybook -p 9001 -c storybook",
...
}
...
}
コマンドを実行し、ビルドします。
cd ~/live
npm run build
build/index.js
が出力されます。
.env.production
試した限りでは、どうしてもうまく.env.production
の内容を反映させられませんでした。
やむを得ませんので、build/index.js
を修正し.env.production
の絶対パスを記述して対応します。
_dotenv2.default.config({
path: env === 'production' ? '.env.production' : '.env'
});
_dotenv2.default.config({
path: env === 'production' ? '/home/mastodon/live/.env.production' : '.env'
});
Passenger設定
詳細はリファレンスを読みましょう。
ここでは、各ディレクティブ毎に最低限必要な設定を記述していきます。
各設定ファイルは環境に応じて適宜読み替えてください。
http
ディレクティブ
http {
passenger_root /home/mastodon/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/passenger-5.1.3;
passenger_ruby /home/mastodon/.rbenv/versions/2.4.1/bin/ruby;
passenger_log_file /var/log/nginx/passenger.log;
passenger_max_pool_size 4;
passenger_max_instances_per_app 3;
}
passenger_root
passenger_ruby
インストール時に自動的に追記されているはずです。
設定ファイルを他のnginxなどから移行してきた場合、これらを追記します。
passenger_log_file
Mastodonアプリケーションのログが出力される先になります。
設定しない場合、これらはnginxのerror_log
に出力されるため、設定しておいた方が良いと思います。
passenger_max_pool_size
passenger_max_instances_per_app
それぞれ、サーバ全体で許可するアプリケーションWorkerインスタンスの最大数、及び各アプリケーション毎のWorkerインスタンスの最大数です。
ここがチューニングの要ですが、ひとまず適当な値を入れておきます。
(後述の動作状態の確認を参照)
max_pool_size
のデフォルト値は6ですが、メモリが1GBしか無いような場合超えてしまいますので下げておきます。
max_instances_per_app
は、max_pool_size
以下で各アプリケーションにうまく割り振られる値を検討します。
今回は、streaming用は1つあれば十分ですので、max_pool_size - 1
としておきます。
server
ディレクティブ - web
passenger_enabled
passenger_app_group_name
port443をlistenしているserverディレクティブ内に追記します。
root /home/mastodon/live/public;
の上あたりが間違いが無いと思います。
server {
passenger_enabled on;
passenger_app_group_name web;
root /home/mastodon/live/public;
}
リバースプロキシ設定を削除
pumaに対するリバースプロキシ設定は不要となるため、削除またはコメントアウトします。
Production guide
の設定例では以下の部分が該当します。
location / {
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://127.0.0.1:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
location
ディレクティブ - streaming
nodeに対するリバースプロキシ設定は不要となるため、削除またはコメントアウトします。
Production guide
の設定例では以下の部分が該当します。
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass http://localhost:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
新しい設定は以下の通りです。
location /api/v1/streaming {
root /home/mastodon/live;
passenger_enabled on;
passenger_app_group_name streaming;
passenger_app_type node;
passenger_startup_file /home/mastodon/live/build/index.js;
tcp_nodelay on;
}
一通り記述が済みましたら、設定に誤りが無いことを確認しておきます。
sudo /opt/nginx/sbin/nginx -t
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
既存のサービス類を停止
この時点から、元の環境ではアクセスできなくなります。
元々試用していたnginxを停止します。
sudo systemctl stop nginx
sudo systemctl disable nginx
mastodon-web
及びmastodon-streaming
を停止します。
sudo systemctl stop mastodon-web
sudo systemctl stop mastodon-streaming
sudo systemctl disable mastodon-web
sudo systemctl disable mastodon-streaming
Passenger + nginxを起動
systemd対応で設定した名前を使用して、起動します。
start/restart/reloadなど、nginxの場合と同様に実行できます。
sudo systemctl enable nginx-passenger
sudo systemctl start nginx-passenger
ブラウザからMastodonにアクセスします。
エラー無く利用できれば、作業完了です。お疲れさまでした:-)
動作状態の確認
passenger-status
コマンドを利用すると、Passengerの動作状態を確認できます。
cd ~/live
passenger-status
Version : 5.1.3
Date : 2017-05-07 07:49:31 +0900
Instance: dqfV6I6e (nginx/1.12.0 Phusion_Passenger/5.1.3)
----------- General information -----------
Max pool size : 4
App groups : 2
Processes : 2
Requests in top-level queue : 0
----------- Application groups -----------
streaming:
App root: /home/mastodon
Requests in queue: 0
* PID: 27481 Sessions: 2 Processed: 4 Uptime: 1h 2m 27s
CPU: 0% Memory : 21M Last used: 30m 26s a
web:
App root: /home/mastodon/live
Requests in queue: 0
* PID: 28733 Sessions: 0 Processed: 3 Uptime: 30m 26s
CPU: 0% Memory : 120M Last used: 23m 8s ago
必要に応じて、Passengerによりweb
のWorkerインスタンスが増減します。
Version : 5.1.3
Date : 2017-05-07 07:51:07 +0900
Instance: dqfV6I6e (nginx/1.12.0 Phusion_Passenger/5.1.3)
----------- General information -----------
Max pool size : 4
App groups : 2
Processes : 4
Requests in top-level queue : 0
----------- Application groups -----------
streaming:
App root: /home/mastodon
Requests in queue: 0
* PID: 27481 Sessions: 2 Processed: 9 Uptime: 1h 4m 3s
CPU: 0% Memory : 21M Last used: 2s ago
web:
App root: /home/mastodon/live
Requests in queue: 0
* PID: 28733 Sessions: 0 Processed: 10 Uptime: 32m 2s
CPU: 0% Memory : 120M Last used: 3s ago
* PID: 29839 Sessions: 0 Processed: 1 Uptime: 6s
CPU: 2% Memory : 46M Last used: 3s ago
* PID: 29849 Sessions: 0 Processed: 0 Uptime: 3s
CPU: 0% Memory : 4M Last used: 3s ago
ここでは詳細は割愛しますが、この状態を見ながら環境に合わせて設定をチューニングすることになると思います。
バージョンアップ
基本はProduction guide
の通りですが、以下の作業が追加となります。
streaming/index.json
このファイルに修正が入った場合、ビルド作業及びビルド後ファイルへの修正が必要です。
アプリケーション再起動
リバースプロキシで運用していたときと同様、アプリケーションはメモリ上で保持されているため再起動するまで更新は反映されません。
次のコマンドで、Passengerが読み込んでいるMastodonを再起動できます。
cd ~/live
passenger-config restart-app /home/mastodon/live
元に戻したくなった……
元のnginxを削除していない場合、今回インストールしたPassenger+nginxを停止し、再びsystemctl
で設定すれば元に戻るはずです。
Passengerが不要になった場合、以下の手順で削除できます。
ファイルパスは適宜読み替えてください。
sudo rm /etc/systemd/system/nginx-passenger.service
sudo rm -rf /opt/nginx
cd ~/live
gem uninstall passenger
git checkout package.json
rm -rf build
-
Mastodon は自分のドメインでIDを持つことが大事。「リモートフォロー」の価値を最大化するべし。 | 諸多日記 ↩
-
具体的にはConoHa VPS メモリ1GBプランです ↩