プロジェクト

全般

プロフィール

丼鯖の建てかた » 履歴 » リビジョン 7

リビジョン 6 (白林檎 美和, 2020/07/16 02:48) → リビジョン 7/9 (白林檎 美和, 2020/08/12 00:27)

# 丼鯖の建てかた 
 ## 材料 
 * 最新のFreeBSD, nginx, PostgreSQL等が走るホスト 
 * データ置き場のストレージ: ユーザーを増やしたり,廃人のやうにつぶやいたりする気満々の方のみ 
 * 80/tcp, 443/tcpへ外からアクセス可能な,イソターネット接続環境 

 ## 準備 
 ### OSのインスコ 
 1. 最新のFreeBSDのディスクイメージを取ってきて,そいつからホストを起動。2020/7/7現在の最新リリースは, [12.1](http://ftp.jaist.ac.jp/pub/FreeBSD/releases/ISO-IMAGES/12.1/)。 
 1. テキストベースのウィザードを,淡々と進める。データ置き場のストレージを,ルートファイルシステムと別に設ける方は,そいつを /usr/home へマウント。 
 1. 丼インスタンスの各種プロセスを実行するためのユーザー “mastodon” を作成。プライマリ以外のグループに, wheelを指定。 
 1. 作業しやすいやう, sshdを有効化。sshdを常駐させるもよし, inetdで必要なときだけ起こすもよし。 

 ### ホストがNATの内側にいる場合 
 1. イソターネットからの80/tcp, 443/tcpへのアクセスを,ホストへ通すよう設定。 
 1. NATの内外どちらからも,同じFQDNでホストへアクセスできるよう, DNS鯖を設定。さうしないと, SSLの証明書を取れなかったり, WWWブラウザで開いたときにSSLが有効にならなかったりする。 

 ## 丼建て 
 ここからは基本的に,公式サイトの[Installing from source](https://docs.joinmastodon.org/admin/install/)の順番で進める。Ubuntu (Debian系Linux) 固有のコマンド等がばしばし出てきて, FreeBSDでは使えないので,読み替えていく。 
 ### Pre-requisites 
 1. /etc/make.conf へ, 次を追加。 

     ``` 
 DEFAULT_VERSIONS+=perl5=5.32 python=3.8 python3=3.8 ruby=2.7 ssl=openssl 
 ``` 
     公式は未だruby 2.6.6を指定していたりするので,心配な方は `ruby=2.6` にするとよい。 
 1. パッケージのオプションを選択。nginxのオプションは, PASSENGERをON。丼では使わないが, Redmine等を建てるときに要る。 
     ``` 
 # portsnap fetch update 
 # don_pkgs='databases/gdbm databases/postgresql12-server databases/postgresql12-contrib databases/redis devel/bison devel/git devel/protobuf devel/protobuf-c devel/bison devel/icu devel/readline dns/libidn graphics/ImageMagick7 multimedia/ffmpeg textproc/libxml2 textproc/libxslt security/openssl security/py-certbot-nginx security/sudo sysutils/rubygem-bundler www/nginx www/yarn-node12' 
 # for pack in don_packs; do make -C /usr/ports/$pack config-recursive; done 
 ``` 
 1. Portsの一括インスコや更新に便利な, portupgradeをインスコ。これがrubyを引き連れてくる。 
     ``` 
 # make -C /usr/ports/ports-mgmt/portupgrade config-recursive install clean 
 ``` 
 1. 丼が使うパッケージを, portsからごりごりインスコ。 
     ``` 
 # portinstall $don_pkgs 
 ``` 
 1. 既存のFreeBSDの環境へ導入する方は,ここでユーザー “mastodon” を作成。bsdconfigの [6    Login/Group Management]→[1    Add Login] なり, adduserなり,お好きな方法で。 
     プライマリ以外のグループに, wheelを指定。 
 1. /usr/local/etc/sudoers の行 `# %wheel ALL=(ALL) ALL` から,先頭の `# ` を削除。 

 ### Setup 
 1. /etc/rc.conf へ次を追加。 

     ``` 
 nginx_enable="YES" 
 postgresql_enable="YES" 
 redis_enable="YES" 
 ``` 
 1. データ置き場を分けた方は, `postgresql_data="/usr/home/postgres/data12"` も追加。既に /var/db/postgres が作られていたら, /usr/home へ移動。 
 1. ぽすぐれを初期化,起動。 
     ``` 
 # service postgresql initdb 
 # service postgresql start 
 ``` 
 1. 丼DB用のユーザーを作成。ついでに,スーパーユーザーへパスワードを付与。 
     ``` 
 # sudo -u postgres psql 
 postgres=# CREATE USER mastodon WITH PASSWORD '<ぱすわぁど>' CREATEDB; 
 postgres=# ALTER ROLE postgres WITH PASSWORD '<ぱすわぁど>'; 
 postgres=# \q    ← ^D 
 ``` 
 1. ユーザーmastodonへ切り替え。 
     ``` 
 # su - mastodon 
 ``` 
 1. 丼鯖の最新リリースを取得。 
     ``` 
 $ git clone https://github.com/tootsuite/mastodon.git live 
 $ cd live 
 $ git checkout <最新リリースのタグ> 
 ``` 
 1. 丼鯖が使う, rubyや農奴のパッケージを, live以下へ配置。`getconf _NPROCESSORS_ONLN` は,ホストのCPUのスレッド数を返す。 
     ``` 
 $ bundle config deployment 'true' 
 $ bundle config without 'development test' 
 $ bundle install -j$(getconf _NPROCESSORS_ONLN) 
 $ yarn install --pure-lockfile 
 ``` 
 1. 初回設定。 
   * DBはUNIX domain socketではなく, localhostを指定。前者では, socketのパス名がUbuntu標準と合わず失敗。 
   * adminのパスワードがランダムに生成されるので,控えておく。 

     ``` 
 $ export RAILS_ENV=production 
 $ bundle exec rake mastodon:setup 
 ``` 
 1. dist/nginx.conf を /usr/local/etc/nginx/mastodon.conf へコピー。 
 1. /usr/local/etc/nginx に nginx.conf がなかったら,nginx.conf-dist をコピー。 
     ``` 
 # cp -p dist/nginx.conf /usr/local/etc/nginx/mastodon.conf 
 # cd /usr/local/etc/nginx 
 # cp -p nginx.conf-dist nginx.conf 
 ``` 
 1. nginx.conf の `http { ... }` から, `server { ... }` を削除。末尾に `include mastodon.conf;` を追加。 
 1. mastodon.conf を編集。 
    1. `server_name` に,ホストのFQDNを記載。 
    1. IPv6を使わない環境 ⇒ `listen [::]:80;`, `listen [::]:443 ssl http2;` をコメントアウト。 
    1. /usr/local/etc/letsencrypt/options-ssl-nginx.conf と重複する,次の行をコメントアウト。 

         ``` 
 ssl_protocols TLSv1.2 TLSv1.3; 
 ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; 
 ssl_prefer_server_ciphers on; 
         ``` 
 1. nginxを起動。 
     ``` 
 # service nginx start 
 ``` 
 1. Let's encryptからSSL証明書を貰う。 
     ``` 
 # certbot --nginx -d <ホストのFQDN> 
 ``` 
 1. mastodon.conf に次の行が足されたのを確認。 
     ``` 
 ssl_certificate /usr/local/etc/letsencrypt/live/<ホストのFQDN>/fullchain.pem; 
 ssl_certificate_key /usr/local/etc/letsencrypt/live/<ホストのFQDN>/privkey.pem; 
 include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot 
 ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot 
 ``` 
 1. nginxを再起動。 
     ``` 
 # service nginx restart 
 ``` 
 1. /etc/periodic.conf に `weekly_certbot_enable="YES"` を追加。同ファイルがなければ作る。 
 1. dist/*.service の内容を基に,丼鯖の各種サービスの起動/終了用スクリプト /usr/local/etc/rc.d/mastodon を作成。最低限start, stop, restartができればよい。 

 ``` shell 
 #!/bin/sh 

 # PROVIDE: mastodon 
 # REQUIRE: nginx postgresql redis 

 . /etc/rc.subr 

 name="mastodon" 
 rcvar="${name}_enable" 

 load_rc_config $name 
 : ${mastodon_enable="NO"} 
 : ${mastodon_user="mastodon"} 
 : ${mastodon_group="<ユーザーmastodonの所属グループ>"} 
 start_cmd="${name}_start &" start_cmd="${name}_start" 
 stop_cmd="${name}_stop" 
 restart_cmd="${name}_restart &" 
 status_cmd="${name}_status" 
 extra_commands="status" restart_cmd="${name}_restart" 

 MASTODON_HOME=/usr/home/mastodon/live 
 BUNDLE=/usr/local/bin/bundle 
 NODE=/usr/local/bin/node 
 DAEMON="/usr/sbin/daemon -u $mastodon_user" 
 PROCS="puma sidekiq node" 
 REQUIRED_PIDS="/var/db/postgres/data12/postmaster.pid /var/run/redis/redis.pid /var/run/nginx.pid" 

 export RAILS_ENV=production 
 export NODE_ENV=production 
 export DB_POOL=25 
 export MALLOC_ARENA_MAX=2 
 export STREAMING_CLUSTER_NUM=1 

 mastodon_start() { 
	 for i in $REQUIRED_PIDS; do 
		 while [ ! -f $i ]; do 
			 echo "$i is not ready." 
			 sleep 1 
		 done 
	 done 
	 sleep 1 
	 cd $MASTODON_HOME 
	 for i in $PROCS; do 
		 pidfile=$i.pid 
		 if [ -f $pidfile ]; then 
			 echo "$i is running as pid $(cat $pidfile)." 
		 else 
			 touch $pidfile 
			 chmod 644 $pidfile 
			 case $i in 
				 puma ) PORT=3000 $DAEMON -p puma.pid -o log/puma.log $BUNDLE exec puma -C config/puma.rb ;; 
				 sidekiq ) $DAEMON -p sidekiq.pid -o log/sidekiq.log $BUNDLE exec sidekiq -c 25 ;; 
				 node ) PORT=4000 $DAEMON -p node.pid -o log/node.log $NODE ./streaming ;; 
			 esac 
			 echo "Started $i." 
		 fi 
	 done 
 } 

 mastodon_stop() { 
	 cd $MASTODON_HOME 
	 for i in $PROCS; do 
		 pidfile=$i.pid 
		 if [ -f $pidfile ]; then 
			 pid=$(cat $pidfile) 
			 kill -s TERM $pid 
			 while kill -0 $pid 2> /dev/null; do 
				 sleep 1 
			 done 
			 rm -f $pidfile 
			 echo "Stopped $i." 
		 else 
			 echo "$i is not running." 
		 fi 
	 done 
	 stty echo 
 } 

 mastodon_restart() { 
	 $stop_cmd 
	 $start_cmd 
 } 

 ippandon_status() { 
	 cd $IPPANDON_HOME 
	 for i in $PROCS; do 
		 pidfile=$i.pid 
		 if [ -f $pidfile ]; then 
			 echo "$i is running as pid $(cat $pidfile)." 
		 else 
			 echo "$i is not running." 
		 fi 
	 done 
 } 

 run_rc_command "$1" 
 ``` 
 1. /etc/rc.conf へ `mastodon_enable="YES"` を追加。 
 1. 丼鯖のサービスを起動。 

     ``` 
 # service mastodon start 
 ``` 
 1. WWWブラウザから https://*ホストのFQDN*/ を開き, adminのメアドと初期パスワードでログイン。あとはページ内から,各種設定を進める。 

 ## ログ回し 
 nginxと丼サービスのログを1週間周期で固めて回すよう, newsyslogを設定。 
 1. /usr/local/etc/newsyslog.conf.d に次のファイルを作成。 
    * nginx.conf 

         ``` 
 # logfilename           [owner:group]    mode    count    size    when     flags    [/pid_file]           [sig_num] 
 /var/log/nginx/*.log                   644     100      *       $W0D0    GX       /var/run/nginx.pid    SIGUSR1 
 ``` 
    * mastodon.conf: “usuaji” は,ユーザーmastodonの所属グループに読み替え。 
         ``` 
 # logfilename                    [owner:group]      mode    count    size    when     flags    [/pid_file]                      [sig_num] 
 /home/mastodon/live/log/*.log    mastodon:usuaji    644     100      *       $W0D0    GRX      /usr/home/mastodon/restart.sh 
 ``` 
 1. /usr/home/mastodon/restart.sh を作成。 
     ``` shell 
 #!/bin/sh 
 service mastodon restart 
 ``` 
 1. newsyslogを再起動。 
     ``` 
 # service newsyslog restart 
 ```