ごらくらいふ

プログラミングしたりゲームしたり

CentOS6.9にMastodonを導入する(Docker 不使用)

多分いろんなタイトルと被っちゃってると思う。でも伝わる文言がこれなんだ。許してほしい。

いちWebServiceインスタンスのためにOS入れ替えなんてしてられるか! 所詮Ruby on Rails、依存をかっさばきゃあいいんでしょう!

Production-guide.mdに沿ってすすめる。

基本的にPackage Managerを使って解決していきたい。

環境

TL;DR

  • CentOS6.9でも Mastodonは動く
  • 札束持ってAWSの扉叩いたほうが百倍、いや万倍は生産性高い

mastodon userを作成しておく

sudo useradd mastodon
sudo passwd mastodon

外部からsshでパスワードログインさせない、だとかは割愛。

Software Collectionを導入しておく

CentOS6.9の標準ではバージョンの足りないパッケージがちらほらあるので、Software Collectionを導入しておく。

sudo yum install centos-release-scl
sudo yum-config-manager --enable rhel-server-rhscl-6-rpms

Apacheを2.4.5以降にする

WebSocket対応のリバースプロキシを提供するmod_proxy_wstunnelが必要だが、Apache 2.4.5以降で有効とのこと。

この件に関しては他でも流用できそうなので別記事にした。

yajamon.hatenablog.com

General Depenciesを解決する

資料を元に解決する。

# これを CentOSナイズする
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file git curl
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -

sudo apt-get install nodejs

sudo npm install -g yarn

ImageMagick

https://www.imagemagick.org/script/index.php

画像操作周りをMastodonで取り扱う際に使ってるのかな。

baseリポジトリ6.7.2.7を使う。

導入方法
sudo yum install ImageMagick

FFmpeg

https://ffmpeg.org/

動画周りの処理を任せてるのかな。

ubuntuでの導入方法しか書いてない理由はこいつのせいじゃないかなと思う。

導入方法

公式ページのDownloadを見るとRPMFusionを案内しているのでそちらから導入してみる。

RPMFusion

http://qiita.com/m2wasabi/items/6d6a68da2e9dada92369#rpmfusion を参考にした。

  • --enablerepo前提でインストールするので元記事のyum-plugin-*は除外

まず自身の環境チェック

cat /etc/redhat-release
# CentOS release 6.9 (Final)
arch
# x86_64

RPM Fusionのページから、必要なリポジトリがどれか判断する。

  • Browse available packagesからffmpegを探してみる
    • CentOS 6.9x86_64
    • freeにありそう
    • applications/multimediaにありそう
    • あった

PGP-Keyのインストール

  • Keysのページから探す
    • freeEL 6のkeyをインストールすればいい
sudo gpg --keyserver pgp.mit.edu --recv-keys 849C449F

リポジトリを追加する

sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-6.noarch.rpm

rpmfusionは初期状態無効とする。

sudo vi /etc/yum.repo.d/rpmfusion-free-updates.repo
[rpmfusion-free-updates]
# enabled=1
enabled=0

yum-config-manager使えっても良かったのかな。

ffmpeg
sudo yum --enablerepo=rpmfusion-free-updates install ffmpeg

libpq-dev

PostgreSQLのライブラリらしい。この文言のままではyumで見つからない。

  • yumで対応するのはpostgresql-develらしい
    • これが無いことで発生するエラーを見ると、必要なヘッダーが無いgem pgを導入する際ビルドが失敗するらしい
    • yum search postgresqlして出てきた結果を見ると、これでよさそう
      • postgresql-devel.x86_64 : PostgreSQL development header files and libraries
導入方法
sudo yum install postgresql-devel

libxml2-dev

yumだとlibxml2-develが対応するのかな。URLは同じ場所を示している。

The XML C parser and toolkit of Gnome http://xmlsoft.org/

導入方法
sudo yum install libxml2-devel

libxslt1-dev

yumだとlibxslt-develが対応するのかな。URLは同じ場所を示している。

なぜ1が無いのだろう…

導入方法
sudo yum install libxslt-devel

nodejs and yarn

anyenv -> nodenv 経由で入れる。

ミーハーなので現時点(2017/04/19)の最新版7.9.0をインストールする。

yarn installでなんか死んだ。 Production-Guideに従って、4.xの最新版である4.8.2を入れた。

原因は別件だった: 下記トラブルシュート参照

とくに考えもなくndenv使ってたけど、コミットが静かなので浮気。(**envに活発性を求めてもしょうがないけど)

nodenvはnodenvでndenv OwnerにJoin持ちかけたりanyenvから他のnode.js系env排斥を持ちかけたりするコミュニティなのでどうなのと思わなくもない。

導入方法
su - mastodon

git clone https://github.com/riywo/anyenv ~/.anyenv
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
exec $SHELL -l

anyenv install nodenv
exec $SHELL -l

nodenv install 4.8.2
nodenv global 4.8.2
npm install -g yarn
nodenv rehash

file, git, curl

特にすり合わせるポイントはない。

導入方法
sudo yum install file git curl

Redis

Sidekiqの要求バージョンが>= 2.8.0とのこと。 epelから入手したRedisでは2.4.xのため、終盤になって問題が発覚して非常に悲しい気持ちになる。

SoftwareCollectionからRedis 3.2を導入する。

導入方法
sudo yum install rh-redis32-redis
# Lockファイルを置くディレクトリが作れておらず拗ねたので対応
sudo mkdir /var/opt/rh/rh-redis32/lock
sudo mkdir /var/opt/rh/rh-redis32/lock/subsys

sudo service rh-redis32-redis start
sudo chkconfig rh-redis32-redis on

PostgreSQL

Ruby on Rails というか ActiveRecordsの要求バージョンが>= 9.1とのことなので、SoftwareCollectionからPostgreSQL 9.5を導入する。

導入方法
sudo yum install rh-postgresql95-postgresql-server
sudo yum install rh-postgresql95-postgresql-contrib

scl enable rh-postgresql95 bash

# rootでの作業 ここから
su -
echo 'source /opt/rh/rh-postgresql95/enable' >> /etc/profile.d/rh-postgresql95.sh
exit
# rootでの作業 ここまで

sudo /opt/rh/rh-postgresql95/root/usr/bin/postgresql-setup --initdb
sudo service rh-postgresql95-postgresql start
sudo chkconfig rh-postgresql95-postgresql on

sudo passwd postgres

mastodonを導入する

PostgreSQL userを作る

su - postgres
psql
CREATE USER mastodon CREATEDB;
\q
# postgres userから抜ける
exit

rbenvを使ってrubyを導入する

su - mastodon

anyenv install rbenv
exec $SHELL -l

rbenv install 2.4.1
rbenv global 2.4.1

mastodon をインストールする

cd ~
git clone https://github.com/tootsuite/mastodon.git live
cd live

gem install bundler
bundle install --deployment --without development test
yarn install

mastodon の環境設定

.env.productionを設定していく。

pwd
# /home/mastodon/live
cp .env.production.sample .env.production
redis

以下を.env.productionの項目で編集する。

REDIS_HOST=localhost
REDIS_PORT=6379
DB (PostgreSQL)

以下を.env.productionの項目で編集する。

DB_HOST=
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=
DB_PORT=5432

mastodon のセットアップ

RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile
サービスの作成

CentOS6.9だし、Systemdは使ってないので/etc/init.d/に配置するほうのサービスとして書き出す。

手探りでstart-stop-deamon無いどころかdeamon使ってないし、というかstartstopしかない。

mastodon-web

#!/bin/bash
#
# Mastodon worker web
#
# chkconfig: - 85 15
# description: Mastodon web

prog="mastodon-web"
username="mastodon"
root="/home/mastodon/live"
pidfile="${root}/web.pid"

start() {
    if [ -f $pidfile ]; then
        echo "Mastodon webservice running..."
        exit 1
    fi
    su - $username -c "cd ${root} && RAILS_ENV=production PORT=3000 bundle exec puma -C config/puma.rb -d --pidfile ${pidfile}"
    return 0
}
stop() {
    if [ -f $pidfile ]; then
        su - $username -c "kill $(cat ${pidfile}) && rm ${pidfile}"
    else
        echo "Mastodon webservice dos'nt running..."
        exit 1
    fi
    return 0
}
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    *)
        echo $"Usage $prog {start|stop}"
        exit 2
esac
exit 0

mastodon-sidekiq

#!/bin/bash
#
# Mastodon worker sidekiq
#
# chkconfig: - 85 15
# description: Mastodon sidekiq

prog="mastodon-sidekiq"
username="mastodon"
root="/home/mastodon/live"
pidfile="${root}/worker.pid"
logfile="${root}/sidekiq.conf"

start() {
    if [ -f $pidfile ]; then
        echo "Mastodon worker sidekiq running..."
        exit 1
    fi
    su - $username -c "cd ${root} && RAILS_ENV=production DB_POOL=5 bundle exec sidekiq -d -P ${pidfile} -L ${logfile} -c 5 -q default -q mailers -q pull -q push"
    return 0
}
stop() {
    if [ -f $pidfile ]; then
        su - $username -c "kill $(cat ${pidfile}) && rm ${pidfile}"
    else
        echo "Mastodon worker sidekiq dos'nt running..."
        exit 1
    fi
    return 0
}
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    *)
        echo $"Usage $prog {start|stop}"
        exit 2
esac
exit 0

mastodon-streaming

#!/bin/bash
#
# Mastodon streaming API service
#
# chkconfig: - 85 15
# description: Mastodon steaming API service

prog="mastodon-streaming-api"
username="mastodon"
root="/home/mastodon/live"
pidfile="${root}/streaming.pid"

start() {
    if [ -f $pidfile ]; then
        echo "Mastodon  streaming API running..."
        exit 1
    fi
    su - $username -c "cd ${root} && NODE_ENV=production PORT=4000 nohup npm run start & echo \$! > ${pidfile}"
    return 0
}
stop() {
    if [ -f $pidfile ]; then
        local pid=$(cat ${pidfile})
        local pgid=$(ps ho pgid -p $pid | sed 's/\s//g')
        for target in $(ps h -g $pgid | sed 's/^\s\+//' | sed 's/\s\+/\t/g' | cut -f1)
        do
            kill $target
        done
        su - $username -c "${pidfile}"
    else
        echo "Mastodon streaming API dos'nt running..."
        exit 1
    fi
    return 0
}
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    *)
        echo $"Usage $prog {start|stop}"
        exit 2
esac
exit 0

上記を/etc/init.d/に配置したら、以下を実行する。

sudo service mastodon-web start
sudo chkconfig mastodon-web on
sudo service mastodon-sidekiq start
sudo chkconfig mastodon-sidekiq on
sudo service mastodon-streaming start
sudo chkconfig mastodon-streaming on
参考資料

CronJobの作成

RAILS_ENV=production
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily > /dev/null

トラブルシュート

yarn installでなんか死んでる

bufferutilなるパッケージがビルドできずに死んでた。死ぬまで眼を凝らしていたらC++11コンパイラが見つかってなさそうだった。

gcc --version
# gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)
g++ --version
# g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)

Software Collectionから最新のDevToolset3を導入した。

sudo yum install devtoolset-3-gcc devtoolset-3-binutils
sudo yum install devtoolset-3-gcc-c++ devtoolset-3-gcc-gfortran

scl enable devtoolset-3 bash

パッケージを導入するたびにscl enableを実行することで有効化できる。 これをシェル起動時毎回呼び出すと手軽らしい。

# rootになる
su -

echo 'source /opt/rh/devtoolset-3/enable' >> /etc/profile.d/devtools.sh

# rootを抜ける
exit

binutilsgfortranがよくわからん。

参考資料

CentOSに新しいバージョンのGCC/G++(4.8/4.9)をインストールする - TASK NOTES http://www.task-notes.com/entry/20151114/1447492231

Devtoolset-3 — Software Collections https://www.softwarecollections.org/en/scls/rhscl/devtoolset-3/

SMTPサーバ用意するのしんどい

.env.production.sampleにも書いてあったけど、SparkPost使えば?とのこと。

SendGridを使用することにした。

さくらの VPS + CentOS7 で 俺専用 Mastodon インスタンスを立ててみた話 | WWW WATCH https://hyper-text.org/archives/2017/04/mastodon-instance-single-user.shtml

PostgreSQLのident認証が通らない!

これのせいでDB作成ができずに2日ほど作業が止まった。

mastodon userでpsqlを叩くとPostgreSQLは起動する。

psql -h localhostとすると、ident認証が通らずうまくいかない。

# local
local trust
# IPv6
host ::128 ident
# IPv4
host 127.0.0.1/32 ident

。。。別にlocalhostのために一旦ネットワーク出る必要なくない?

ということで.env.productionからDB_HOSTの値がなくなった。

S3にうまくアップロードできない

参考資料を元に進めたところ、S3へのアップロードで500エラーがかえってきたりした。 ポイントは多分以下だと思う。

# 東京リージョンでの設定
S3_HOSTNAME=s3-ap-northeast-1.amazonaws.com
# ENDPOINTを明記する場合、https:// を付けておく
S3_ENDPOINT=https://s3-ap-northeast-1.amazonaws.com

情報源ごとに情報がブレるのは、Mastodonのバージョンによって挙動が違ったのかもしれない。 この情報は、Mastodon 1.2.2で確認している。

参考資料

自分でアップロードしたのはS3に上がるが、リモートフォローした人のアイコンとかS3に上がらない

S3設定の更新をしたら、Sidekiqの再起動も必要だった。

リモートフォロー周りはSidekiq Workerが取り持ってくれてるが、S3設定後に再起動を忘れると、ローカルに保存する設定のままになっている。

所感

  • Mastodon 楽しい
  • こんだけ手間かかるならそらCentOSじゃなくてUbuntuでやるわ
  • ケチって過去にVPS内におっ立てたOSでちびちびやるより、AWSへ札束でノックしに行くなりしたほうが百倍、いや万倍は生産性高い

CentOS6.9にて、Apacheを2.4に更新した

前提

経緯

MastodonApache上で動かすため、WebSocket対応のリバースプロキシを提供するmod_proxy_wstunnelが必要だった。 これは、Apache 2.4.5以降で有効とのことなので、2.4系のパッケージを導入する必要が生まれた。

手順

Software Collcetionを導入する

CentOS6.9の標準ではApache2.2までしかないので、Software Collectionを導入する。

sudo yum install centos-release-scl
sudo yum-config-manager --enable rhel-server-rhscl-6-rpms

必要なパッケージの検索

sudo yum search httpd24を実行して、必要そうなパッケージを選ぶ。 自分の場合は以下。

  • httpd24-httpd
  • httpd24-mod_proxy_html
  • httpd24-mod_session
  • httpd24-mod_ssl

パッケージのインストー

sudo yum install httpd24-httpd httpd24-mod_proxy_html httpd24-mod_session httpd24-mod_ssl
scl enable httpd24 bash

# rootでの作業
su -
echo 'source /opt/rh/httpd24/enable' >> /etc/profile.d/httpd24.sh
exit

コンテンツの移植

Software Collectionで導入すると/opt/rh/httpd/root/の下にFilesystem Hierarchy Standard状のディレクトリ構成が広がっている。 諸々と共存できるようにするためだろうが、いざ旧環境とのすり合わせをするとなると非常にだるい

cp -av {/var/www,/opt/rh/httpd/root/var/www}/#コピーしたいディレクトリを指定する

設定の移植

元々の設定をhttpd.conf.orgで残しているので、当時の設定内容を抽出する。

diff /etc/httpd/conf/httpd.conf{,.org} > httpd.conf.diff
# オリジナルを残しておいてもりもり修正する
sudo cp -v /opt/rh/httpd/root/etc/httpd/conf/httpd.conf{,.org}
sudo vi /opt/rh/httpd/root/etc/httpd/conf/httpd.conf
# includeされるように書くもよし
sudo vi /opt/rh/httpd/root/etc/httpd/conf.d/other.conf

その他、/etc/httpd/conf.d/*.conf/opt/rh/httpd24/root/etc/httpd/conf.d/にコピーする。

cp -av {/etc/httpd/conf.d,/opt/rh/httpd/root/etc/httpd/conf.d}/#コピーしたいconfを指定する

シンボリックリンクの作成

標準の位置にすり替える。

sudo mv -v /etc/{,_}httpd
sudo ln -s /opt/rh/httpd24/root/etc/httpd/ /etc/httpd

sudo mv -v /var/{,_}www
sudo ln -s /opt/rh/httpd24/root/var/www/ /var/www

Apacheの起動

# 起動済みの古いApacheを止める
sudo service httpd stop
sudo chkconfig httpd off

sudo service httpd24-httpd start
sudo chkconfig httpd24-httpd on

トラブルシュート

RewriteLogで怒られる

Apache2.4ではRewriteLogはなくなっている網様。LogLevelを使えとのこと。

LogLevel crit

これまで使っていたPHPが使いまわせない

どうも2.2で動かしていた頃のPHPでは参照できないシンボルがあった模様。

まぁ、SoftwareCollectionのApacheを使うようになるのだから、その上で動くPHPもSoftwareCollection化するのは必然。

apache2.4が動いている状態でinstallすれば特に困らず動かせるはず。

sudo yum install rh-php70-php
scl enable rh-php70 bash
# rootでの作業
su -
echo 'source /opt/rh/rh-php70/enable' >> /etc/profile.d/rh-php70.sh
exit

genomirai.comのWORD_DUMPをパースする

おもむろに http://www.genomirai.com をやりたくなった。

プレイ中DUMPされた文字列が出力される場合があるが、ドラッグして選択しようとするとクリックが反応して先に進んでしまう。

ということでjavascriptコンソールに突っ込んで解決した。chromeでしか確認していない。

var dumps = $$("span")
    .map(el => el.innerText.trim())
    .join("")
    .match(/FF FE.+?(?===DUMP)/g);
if(dumps){
    dumps.map(str => str.replace(/\s/g,""))
        .map(str => str.match(/.{4}/g)
            .map(word => word.match(/.{2}/g)
                .reverse()
                .join("")
            )
            .map(word => "%u"+word)
            .join("")
        )
        .map(str => unescape(str))
        .forEach( str => console.log(str))
}

きょうの元気なうちに集中が切れてもできる仕事を組み立てよう。とかやる暇があったら動いたほうがマシ。

やることリスト書き出しとかするじゃないですか。

ダメになったパーの自分に向けて作業リスト作るのって、まぁ他人に作業指示書を作るのと同じであって、 詳細設計書とかいう机上の空論のかみっぺら。

メソッドひとつとっても本当に想定の値が取得できるか試してみないとわからない。試してみたならもう組み込んでおけよと。

できそうだな。と思ってできなかった時にパーになった自分は役に立たないので、元気なうちに実装入ろう。 パーになったらとっとと帰って寝て早く来てパーになってのサイクルを回せばいいや。

と、パーになった今帰らずブログで垂れ流している。

Minecraftのバックアップが動作していなかったのを修正した作業ログ

放置状態のMinecraft、久しぶりに様子を見てみたらバックアップに失敗していた。 はてどうしたものかとcronからの通知を確認すると

Date: Tue, 21 Feb 2017 04:00:01 +0900 (JST)

minecraft_server.jar is running... suspending saves
Backing up minecraft world...
tar: VPSworld: stat 不能: そのようなファイルやディレクトリはありません
tar: 前のエラーにより失敗ステータスで終了します
Backing up minecraft_server.jar
minecraft_server.jar is running... re-enabling saves
Compressing backup...
Done.

oh…

どこがトラブルポイントなのか調べる

まずはcronの確認から。現象は4時に報告されている。

# crontab -l
30 4 * * * /etc/init.d/minecraft restart
0 4 * * * /etc/init.d/minecraft backup

4時に実行されるコマンドはminecraft backup

もうどこから持ってきたか忘れてしまったminecraftコマンドの中身を漁る。

case "$1" in
  # 略
  backup)
    mc_backup
    ;;
  # 略
esac

mc_backupのみ

mc_backup() {
  mc_saveoff

  NOW=`date "+%Y-%m-%d_%Hh%M"`
  BACKUP_FILE="$BACKUPPATH/${WORLD}_${NOW}.tar"
  echo "Backing up minecraft world..."
  #as_user "cd $MCPATH && cp -r $WORLD $BACKUPPATH/${WORLD}_`date "+%Y.%m.%d_%H.%M"`"
  as_user "tar -C \"$MCPATH\" -cf \"$BACKUP_FILE\" $WORLD"

  echo "Backing up $SERVICE"
  as_user "tar -C \"$MCPATH\" -rf \"$BACKUP_FILE\" $SERVICE"
  #as_user "cp \"$MCPATH/$SERVICE\" \"$BACKUPPATH/minecraft_server_${NOW}.jar\""

  mc_saveon

  echo "Compressing backup..."
  as_user "gzip -f \"$BACKUP_FILE\""
  echo "Done."
}

echoの内容から、as_user "tar -C \"$MCPATH\" -cf \"$BACKUP_FILE\" $WORLD"になにかあったことがわかる。

tar コマンドのオプション

  • -C : change directory
  • -c : 書庫の作成モードとして動作する
  • -f ファイル名 : 指定した書庫ファイルまたはデバイスを(書き込みに)使用する

Linuxコマンド集 - 【 tar 】 ファイルを書庫化・展開する(拡張子.tarなど):ITpro

あやしいわーるど

$WORLDは何を指しているのか
# grep "WORLD=" minecraft
WORLD='VPSworld'
minecraftはどのサーバを使っているのか
# grep "level-name" server.properties
level-name=world

全部こいつのせいだ。

対応ログ

ワールドディレクトリを変更して対応

# 作業に入る前にminecraftを確実に停止させる

# sudo service minecraft stop
minecraft_server.jar was not running.
minecraft_server.jar is stopped.


# ワールドディレクトリの名前変更

#  mv -v world VPSworld
`world' -> `VPSworld'


# サーバー設定の変更

# cp -v server.properties{,.org}
`server.properties' -> `server.properties.org'

# vi server.properties

#  diff server.properties{,.org}
28c28
< level-name=VPSworld
---
> level-name=world

バックアップの動作確認

# sudo service minecraft backup
minecraft_server.jar is not running. Not suspending saves.
Backing up minecraft world...
Backing up minecraft_server.jar
minecraft_server.jar is not running. Not resuming saves.
Compressing backup...
Done.

# ll -h backup/
#  ======省略======
-rw-r--r-- 1 minecraft minecraft  184  221 04:00 2017 VPSworld_2017-02-21_04h00.tar.gz
-rw-rw-r-- 1 minecraft minecraft 109M  221 13:36 2017 VPSworld_2017-02-21_13h36.tar.gz

圧倒的容量差

稼働開始

# sudo service minecraft start
Starting minecraft_server.jar...
minecraft_server.jar is now running.

PS4のHDDを2TBに換装した

DL版主体でやってきた結果、ついに付属HDDの容量が尽きた。

わりと持ったほうだけど、FFXVやBloodBorneやら50GB級のもの買い出すと恐ろしいほど容量が減る。

作業は4Gamerを参考にしたら出来た。

www.4gamer.net

以上。

以下買ったHDDのアフィ。

ニコニコマイリストRSSをSlackに吸い上げて貰うようにした

yajamon.hatenablog.com

feedlyで受けるの止めました。

記事の末尾にあるけど、通知先にSlackを選択したのなら、RSSインテグレーションで十分なのよね。

基本的にfeedlyRSSを登録するのは以下を目的にしている。

  • 新着を素早く受信するため
  • 加えて、読むか読まないかの仕分けをするため
    • 読む記事はPocketに送る(IFTTT経由
      • Pocketを使うのは、RSSフィード以外にも後で読む記事があり、それと統合するため

で、マイリストの新着なんて基本全部観たいし、通知先プラットフォームをSlackにしてるし、feedlyを外した。