AWS Amazon LinuxでのMastodonのインストール

AWS Amazon LinuxでのMastodonのインストール手順です。Mastodonのインストールは、Dockerを使用するのがポピュラーなようですが、仮想環境であるEC2に更にDockerという仮想環境を重ねるのも無駄な気がするので、Dockerは使用していません。インストールするものが多くて挫けそうになると思いますが、がんばってください。なお、”example.com”となっている部分は、ご自身のサイトのURLに書き換えてください。

【参考ページ】
Mastodon を CentOS にインストールする (Docker未使用)

AWSのAmazon Linux AMIでのffmpegのコンパイル方法

CompilationGuide/Centos – FFmpeg

Let’s Encrypt サーバー証明書の取得と自動更新設定メモ

EC2上のLet’s Encrypt SSLの更新でエラー発生

ImageMagick

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

yum install ImageMagick

依存ライブラリ

必要な依存ライブラリなどをインストールします。

yum install autoconf automake cmake freetype-devel gcc gcc-c++ git libtool make mercurial nasm pkgconfig zlib-devel

FFmpeg

ソースコードを保存するディレクトリを作成します。

mkdir ~/ffmpeg_sources

Yasm

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

cd ~/ffmpeg_sources
git clone --depth 1 git://github.com/yasm/yasm.git
cd yasm
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
make
make install

libx264

libx264をインストールする。

cd ~/ffmpeg_sources
git clone --depth 1 git://git.videolan.org/x264
cd x264
PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static
make
make install

libx265

libx265をインストールする。

cd ~/ffmpeg_sources
hg clone https://bitbucket.org/multicoreware/x265

encoder.hにタイポがあるので修正する。

cd ~/ffmpeg_sources/x265/source/encoder
vim encoder.h
// #include "dynamicHDR10\hdr10plus.h"
#include "dynamicHDR10/hdr10plus.h"
cd ~/ffmpeg_sources/x265/build/linux
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/ffmpeg_build" -DENABLE_SHARED:bool=off ../../source
make
make install

下記メッセージが出力されるが問題ない(たぶん)。

Could NOT find NUMA (missing: NUMA_ROOT_DIR NUMA_INCLUDE_DIR NUMA_LIBRARY)

libfdk_aac

cd ~/ffmpeg_sources
git clone --depth 1 git://git.code.sf.net/p/opencore-amr/fdk-aac
cd fdk-aac
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install

libmp3lame

cd ~/ffmpeg_sources
curl -L -O http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz
tar xzvf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --disable-shared --enable-nasm
make
make install

libopus

cd ~/ffmpeg_sources
git clone http://git.opus-codec.org/opus.git
cd opus
autoreconf -fiv
PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install

libogg

cd ~/ffmpeg_sources
curl -O http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz
tar xzvf libogg-1.3.2.tar.gz
cd libogg-1.3.2
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install

libvorbis

cd ~/ffmpeg_sources
curl -O http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.4.tar.gz
tar xzvf libvorbis-1.3.4.tar.gz
cd libvorbis-1.3.4
./configure --prefix="$HOME/ffmpeg_build" --with-ogg="$HOME/ffmpeg_build" --disable-shared
make
make install

libvpx

cd ~/ffmpeg_sources
git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git
cd libvpx
./configure --prefix="$HOME/ffmpeg_build" --disable-examples
make
make install

FFmpeg

cd ~/ffmpeg_sources
curl -O http://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
tar xjvf ffmpeg-snapshot.tar.bz2
cd ffmpeg
PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib -ldl" --bindir="$HOME/bin" --pkg-config-flags="--static" --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265
make
make install

Redis

rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
yum --enablerepo=remi install redis
service redis start
chkconfig --list | grep redis

postgresql

yum localinstall -y https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm
yum install -y postgresql96 postgresql96-server postgresql96-libs postgresql96-contrib postgresql96-devel
/etc/init.d/postgresql-9.6 initdb --encoding=UTF-8 --locale=ja_JP.UTF-8 --data-checksums
/etc/init.d/postgresql-9.6 start
ln -s /usr/pgsql-9.6/bin/* /usr/local/bin/
sudo su - postgres -c 'psql -c "CREATE USER mastodon CREATEDB;"'
sed -i.org '/shared_preload_libraries/ s/^#//' /var/lib/pgsql/9.6/data/postgresql.conf
sed -i "/shared_preload_libraries/ s/''/'pg_stat_statements'/" /var/lib/pgsql/9.6/data/postgresql.conf
sed -i "/shared_preload_libraries/a pg_stat_statements.track = all" /var/lib/pgsql/9.6/data/postgresql.conf
/etc/init.d/postgresql-9.6 restart
chkconfig postgresql-9.6 on

nginx

yum install nginx
service nginx start
chkconfig nginx on

Node.js

curl -sL https://rpm.nodesource.com/setup_6.x | bash
yum install nodejs

Yarn

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

Ruby

Ruby 2.4.1をインストールする。

yum install bzip2 gcc-c++ git {openssl,readline,zlib}-devel
useradd mastodon
passwd 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 2.4.1 && rbenv global $_ && rbenv rehash

bundler

gem install bundler

Mastodon

Mastodonのインストール

cd ~ && git clone https://github.com/tootsuite/mastodon.git live && cd live
git checkout $(git tag | tail -n 1)
bundle install --deployment --without development test
yarn install

Mastodonの.env.productionファイルの作成

cp .env.production.sample .env.production
sed -i '/^REDIS_HOST=/ s/redis/localhost/' .env.production
sed -i '/^DB_HOST=/ s/db//' .env.production
sed -i '/^DB_USER=/ s/postgres/mastodon/' .env.production
sed -i '/^DB_NAME=/ s/postgres/mastodon/' .env.production
sed -i '/^LOCAL_DOMAIN=/ s/example.com/127.0.0.1:3000/' .env.production
sed -i '/^LOCAL_HTTPS=/ s/true/false/' .env.production
sed -i "/^PAPERCLIP_SECRET=$/ s/$/`rake secret`/" .env.production
sed -i "/^SECRET_KEY_BASE=$/ s/$/`rake secret`/" .env.production
sed -i "/^OTP_SECRET=$/ s/$/`rake secret`/" .env.production

Mastodonのセットアップ

bundle exec rails db:setup RAILS_ENV=production
bundle exec rails assets:precompile RAILS_ENV=production

Mastodonのproduction.rbの修正

Mastodonをアプリケーション・サーバーのPumeで起動すると、ユーザー認証機能を提供するgemのDeviseから送信されるメールに記載されるURLが3000ポートになってしまうので、production.rbを修正します。

cd /home/mastodon/live/config/environments
vim vim production.rb
config.action_mailer.default_url_options = { host: 'example.com', port: 443 }

Mastodonのサービス化

アプリケーションサーバーのPumaをサービスとして起動します。このスクリプトだと、指定したパスにpidファイルを保存できないので、コメントアウトしてあります。手動でプロセスを殺すときは、とりあえず、psコマンドでpidを確認してkillしてください。

cat << "_EOF_" > /etc/init.d/puma
#!/bin/bash
# chkconfig: - 85 15
# description: puma

. /etc/rc.d/init.d/functions

NAME=puma

#USER=mastodon
WORK_PATH=/home/mastodon/live

#UPID=$WORK_PATH/tmp/pids/$NAME.pid
UPID=/var/run/puma.pid
ULOCK=/var/lock/subsys/$NAME

OPTS="-C $WORK_PATH/config/puma.rb -e production"

RUBY_PATH_PATCH="PATH=$PATH:/usr/local/bin:/usr/local/lib && export PATH && "
BUNDLE_CMD=/home/mastodon/.rbenv/shims/bundle
PUMA_CMD=puma

start() {
cd $WORK_PATH
echo -n $"Starting $NAME: "
#daemon --pidfile=$UPID --user=$USER "$RUBY_PATH_PATCH $BUNDLE_CMD exec $PUMA_CMD $OPTS"
daemon --pidfile=$UPID "$RUBY_PATH_PATCH $BUNDLE_CMD exec $PUMA_CMD $OPTS"
ret=$?
[ $ret -eq 0 ] && touch $ULOCK
echo

return $puma
}

stop() {
cd $WORK_PATH
echo -n $"Stopping $NAME: "
killproc -p $UPID
ret=$?
[ $ret -eq 0 ] && rm -f $ULOCK
echo

return $puma
}

restart() {
stop
start
}

get_status() {
status -p $UPID $NAME
}

query_status() {
get_status >/dev/null 2>&1
}

case "$1" in
start)
query_status && exit 0
start
;;
stop)
query_status || exit 0
stop
;;
restart)
restart
;;
status)
get_status
exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|status}" >&2
exit 1
;;
esac

exit 0
_EOF_

Sidekiqのサービス化

cat << "_EOF_" > /etc/init.d/sidekiq
#!/bin/bash
# chkconfig: - 85 15
# description: sidekiq

. /etc/rc.d/init.d/functions

NAME=sidekiq

WORK_PATH=/home/mastodon/live

UPID=/var/run/$NAME.pid
ULOCK=/var/lock/subsys/$NAME

OPTS="-e production -c 5 -q default -q mailers -q pull -q push"

RUBY_PATH_PATCH="PATH=$PATH:/usr/local/bin:/usr/local/lib && export PATH && "
BUNDLE_CMD=/home/mastodon/.rbenv/shims/bundle
CMD=sidekiq
start() {
cd $WORK_PATH
echo -n $"Starting $NAME: "
daemon --pidfile=$UPID "$RUBY_PATH_PATCH $BUNDLE_CMD exec $CMD $OPTS"
ret=$?
[ $ret -eq 0 ] && touch $ULOCK
echo

return $ret
}

stop() {
cd $WORK_PATH
echo -n $"Stopping $NAME: "
killproc -p $UPID
ret=$?
[ $ret -eq 0 ] && rm -f $ULOCK
echo

return $ret
}

restart() {
stop
start
}

get_status() {
status -p $UPID $NAME
}

query_status() {
get_status >/dev/null 2>&1
}

case "$1" in
start)
query_status && exit 0
start
;;
stop)
query_status || exit 0
stop
;;
restart)
restart
;;
status)
get_status
exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|status}" >&2
exit 1
;;
esac

exit 0
_EOF_
chmod 755 sidekiq

streamingのサービス化

cat << "_EOF_" > /etc/init.d/streaming
#!/bin/bash
# chkconfig: - 85 15
# description: streaming

. /etc/rc.d/init.d/functions

NAME=streaming

WORK_PATH=/home/mastodon/live

UPID=/var/run/$NAME.pid
ULOCK=/var/lock/subsys/$NAME

OPTS="-e production"

NODE_ENV=production
PORT=4000

RUBY_PATH_PATCH="PATH=$PATH:/usr/local/bin:/usr/local/lib && export PATH && "
BUNDLE_CMD=/home/mastodon/.rbenv/shims/bundle
CMD="/usr/bin/npm run start"
start() {
cd $WORK_PATH
export NODE_ENV
export PORT
echo -n $"Starting $NAME: "
daemon --pidfile=$UPID "$RUBY_PATH_PATCH $BUNDLE_CMD exec $CMD $OPTS"
ret=$?
[ $ret -eq 0 ] && touch $ULOCK
echo

return $ret
}

stop() {
cd $WORK_PATH
echo -n $"Stopping $NAME: "
killproc -p $UPID
ret=$?
[ $ret -eq 0 ] && rm -f $ULOCK
echo

return $ret
}

restart() {
stop
start
}

get_status() {
status -p $UPID $NAME
}

query_status() {
get_status >/dev/null 2>&1
}

case "$1" in
start)
query_status && exit 0
start
;;
stop)
query_status || exit 0
stop
;;
restart)
restart
;;
status)
get_status
exit $?
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|status}" >&2
exit 1
;;
esac

exit 0
_EOF_
chmod 755 streaming

Mastodonのデイリータスクのcronへの設定

cat << "_EOF_" | crontab -
RAILS_ENV=production
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily > /dev/null
_EOF_

Query stats の有効化

sudo su – postgres -c ‘psql -d mastodon -c “CREATE extension pg_stat_statements;”‘
sudo su – postgres -c ‘psql -d mastodon -c “SELECT pg_stat_statements_reset();”‘

管理者設定

とりあえず、mastodonにユーザー登録し、登録したユーザーを管理者にする。

RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME=admin
RAILS_ENV=production bundle exec rails mastodon:confirm_email USER_EMAIL=admin@example.com

Lets’s Encrypt

無料のSSL証明書のLets’s Encryptをセットアップします。

yum install mod24_ssl
yum install git
cd /usr/local/
git clone https://github.com/certbot/certbot
cd ccertbot
./certbot-auto -n --debug
./certbot-auto certonly --webroot -w /usr/share/nginx/html -d example.com -m webmaster@example.com --agree-tos -n

Lets’s Encryptの証明書の有効期間は3ヶ月なので、月に1回自動更新を行うようにcronに設定します。

crontab -e
40 4 7 * * /usr/local/certbot/certbot-auto renew --force-renewal && /sbin/service httpd restart

nginxの設定ファイルを作成し、SSL証明書のパスなどを指定します。

cat << "_EOF_" > /etc/nginx/conf.d/mastodon.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;

ssl_protocols TLSv1.2;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;

keepalive_timeout 70;
sendfile on;
client_max_body_size 0;

root /home/mastodon/live/public;

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
# add_header Content-Security-Policy "default-src 'none'; style-src 'self'; script-src 'self' https://example.com; img-src 'self' https://example.com; connect-src 'self' wss://example.com; font-src 'self'; frame-ancestors 'none'; media-src 'self';";

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 /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;
}

error_page 500 501 502 503 504 /500.html;
}
_EOF_

nginxを再起動する。

/etc/rc.d/init.d/nginx restart

Postfix

ユーザー登録時のメールアドレスの実在確認や、パスワード忘れのメールなど、色々メールを送信する必要があるので、Postfixをインストールします。

yum install postfix

設定ファイルを編集する。

vim /etc/postfix/main.cf
myhostname = mail.example.site
mydomain = example.com
myorigin = $mydomain
inet_protocols = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain # $mydomainを有効にする。
mynetworks = 127.0.0.0/8

sendmailを停止する。

/etc/rc.d/init.d/sendmail stop
chkconfig sendmail off

postfixを起動する。

/etc/rc.d/init.d/postfix start

デフォルトMTAを変更する。

alternatives --config mta
2 プログラムがあり 'mta' を提供します。
選択 コマンド
-----------------------------------------------
* 1 /usr/sbin/sendmail.sendmail
+ 2 /usr/sbin/sendmail.postfix
Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2

postfixの自動起動をオンにする。

chkconfig postfix on

メールコマンドをインストールする。

yum install -y mailx

メール送信をテストする。

echo "本文" | mail -s "test" webmaster@example.com

メールを送信できることを確認したら、Mastodonの.env.productionファイルを修正します。

cd /home/mastodon/live
vim .env.production
SMTP_SERVER=127.0.0.1
SMTP_PORT=25
SMTP_FROM_ADDRESS=webmaster@example.com

SPFレコードの設定

Gmailとかで迷惑メールに振り分けされるの避けるため、Route 53でSPFレコードを設定します。

以上