LoginSignup
10

More than 5 years have passed since last update.

Zulip のインストールスクリプトを読んだ (1/2)

Last updated at Posted at 2015-11-08

はじめに

インストール手順に従ってグループチャットアプリ Zulip をインストールして動かしてみました。が、マシンを再起動するとメッセージを送受信できなくなりました。何かが動いていないっぽい・・・README.prod.md によると、Zulip は下記のサービスを利用しているとのこと。

  • postgresql
  • rabbitmq-server
  • nginx
  • redis
  • memcached

私は Zulip を AWS EC2 にインストールしたのですが、エラーログを読むと RabbitMQ の起動に失敗していました。ということで、インストールのスクリプトを読んで何がどのようにインストールされて動いているかを覚書にしていきます。

対象バージョンとインストール手順

リンク先のページを読んで Zulip 1.3.7 をインストールしました。

インストールスクリプト

スクリプトは次の順序で実行されます。

  1. zulip/scripts/setup/install
  2. zulip/scripts/lib/install
  3. zulip/scripts/zulip-puppet-apply
  4. zulip/puppet/zulip/manifests/voyager.pp
  5. zulip/scripts/setup/configure-rabbitmq
  6. zulip/scripts/setup/initialize-database

zulip/scripts/setup/install

#!/bin/bash
set -e
set -o pipefail
if [ "$EUID" -ne 0 ]; then
    echo "Error: The installation script must be run as root" >&2
    exit 1
fi
mkdir -p /var/log/zulip
"$(dirname "$(dirname "$0")")/lib/install" "$@" 2>&1 | tee -a /var/log/zulip/install.log

エラーがあればスクリプトを中止する。
パイプライン内のエラーで中止する。
root ユーザーでなければスクリプトを異常終了させる。
/var/log/zulip にディレクトリを作る。
zulip/scripts/lib/install を実行する。
エラー出力を標準出力に結合して /var/log/zulip/install.log にログ出力する。

zulip/scripts/lib/install

First, install any updates from the apt repo that may be needed

#!/bin/bash -xe

0 以外のステータスで終了した場合は直ちに終了する。
readline で行を取得する。

# Assumes we've already been untarred

# First, install any updates from the apt repo that may be needed
wget -O /root/zulip-ppa.asc https://zulip.com/dist/keys/zulip-ppa.asc
apt-key add /root/zulip-ppa.asc
cat >/etc/apt/sources.list.d/zulip.list <<EOF
deb http://ppa.launchpad.net/tabbott/zulip/ubuntu trusty main
deb-src http://ppa.launchpad.net/tabbott/zulip/ubuntu trusty main
EOF

apt-get update
apt-get -y dist-upgrade
apt-get install -y puppet git python

apt の公開鍵を追加する。
パッケージのダウンロード元を指定する。
パッケージリストを更新する。
ディストリビューションをアップグレードする。
puppet git python をインストールする。

mkdir -p /etc/zulip
echo -e "[machine]\npuppet_classes = zulip::voyager\ndeploy_type = voyager" > /etc/zulip/zulip.conf
/root/zulip/scripts/zulip-puppet-apply -f

/etc/zulip にディレクトリを作る。
/etc/zulip/zulip.conf に設定ファイルを書き込む。

zulip.conf
[machine]
puppet_classes = zulip::voyager
deploy_type = voyager

zulip/scripts/zulip-puppet-apply を実行する。

These server restarting bits should be moveable into puppet-land, ideally

apt-get -y upgrade
if [ -e "/etc/init.d/nginx" ]; then
    service nginx restart
fi

インストールされているパッケージを更新する。
Nginx を再起動する。

/root/zulip/scripts/setup/generate_secrets.py
cp -a /root/zulip/zproject/local_settings_template.py /etc/zulip/settings.py
ln -nsf /etc/zulip/settings.py /root/zulip/zproject/local_settings.py

generate_secrets.py を実行する。
local_settings_template.py を /etc/zulip/settings.py にコピーする。
/etc/zulip/settings.py に /root/zulip/zproject/local_settings.py からシンボリックリンクを張る。

if ! rabbitmqctl status >/dev/null; then
    set +x
    echo; echo "RabbitMQ seems to not have started properly after the installation process."
    echo "Often, this can be caused by misconfigured /etc/hosts in virtualized environments"
    echo "See https://github.com/zulip/zulip/issues/53#issuecomment-143805121"
    echo "for more information"
    echo
    set -x
    exit 1
fi

/root/zulip/scripts/setup/configure-rabbitmq

RabbitMQ が起動していなければ異常終了する。

/root/zulip/scripts/setup/configure-rabbitmq

/root/zulip/scripts/setup/postgres-init-db

configure-rabbitmq を実行する。
postgres-init-db を実行する。

deploy_path=$(/root/zulip/zulip_tools.py make_deploy_path)
mv /root/zulip "$deploy_path"
ln -nsf /home/zulip/deployments/next /root/zulip
ln -nsf "$deploy_path" /home/zulip/deployments/next
ln -nsf "$deploy_path" /home/zulip/deployments/current
ln -nsf /etc/zulip/settings.py "$deploy_path"/zproject/local_settings.py
cp -rT "$deploy_path"/prod-static/serve /home/zulip/prod-static
chown -R zulip:zulip /home/zulip /var/log/zulip /etc/zulip/settings.py
chown zulip:zulip /var/run/supervisor.sock

zulip_tools.py make_deploy_path を実行し deploy_path を取得する。
/root/zulip を $deploy_path に移動する。
シンボリックリンクを張る。

/home/zulip/deployments/next /root/zulip
"$deploy_path" /home/zulip/deployments/next
"$deploy_path" /home/zulip/deployments/current
/etc/zulip/settings.py "$deploy_path"/zproject/local_settings.py

"$deploy_path"/prod-static/serve を /home/zulip/prod-static にコピーする。
ファイルとディレクトリと所有者を zulip:zulip に変更する。

cd /home/zulip/deployments/current

set +x
cat <<EOF
 Installation complete!
 Now edit /etc/zulip/settings.py and fill in the mandatory values.
 Once you've done that, please run:
 su zulip -c /home/zulip/deployments/current/scripts/setup/initialize-database
 To configure the initial database.
EOF

/home/zulip/deployments/current に移動する。

zulip/scripts/zulip-puppet-apply

#!/usr/bin/python

import sys
import subprocess
import ConfigParser
import re

次のモジュールをインポートする。

  • システムパラメータと関数
  • サブプロセス管理
  • 設定ファイルの構文解析器
  • 正規表現操作
force = False
extra_args = sys.argv[1:]

if len(extra_args) and extra_args[0] in ('-f', '--force'):
    force = True
    extra_args = extra_args[1:]

config = ConfigParser.RawConfigParser()
config.read("/etc/zulip/zulip.conf")

第一引数が -f ならば force = True にする。
zulip.conf を読み込む。

puppet_config = """
Exec { path => "/usr/sbin:/usr/bin:/sbin:/bin" }
include apt
"""

puppet_config を設定する。

for pclass in re.split(r'\s*,\s*', config.get('machine', 'puppet_classes')):
    puppet_config += "include %s\n" % (pclass,)

Puppet のクラスを puppet_config に追加する。

puppet_cmd = ["puppet", "apply", "--modulepath=/root/zulip/puppet", "-e", puppet_config]
puppet_cmd += extra_args

/root/zulip/puppet を Puppet の実行対象にする。

if force:
    subprocess.check_call(puppet_cmd)
    sys.exit(0)

force が True なら、Puppet を実行する。コマンド実行後、正常終了する。

subprocess.check_call(puppet_cmd + ['--noop', '--show_diff'])

Puppet を実行せず、差分を表示する。

do_apply = None
while not (do_apply == 'y' or do_apply == 'n'):
    sys.stdout.write("Apply changes? [y/N] ")
    do_apply = sys.stdin.readline().strip().lower()
    if do_apply == '':
        do_apply = 'n'

変更を適用するかを問い合わせる。

if do_apply == 'y':
    subprocess.check_call(puppet_cmd)

選択が 'y' なら、Puppet を実行する。

zulip/puppet/zulip/manifests/voyager.pp

class zulip::voyager {
  include zulip::base
  include zulip::app_frontend
  include zulip::postgres_appdb
  include zulip::redis

他のクラスをインクルードする。
これらの詳細は Zulip のインストールスクリプトを読んだ (2/2) に書きます。

  apt::source {'zulip':
    location    => 'http://ppa.launchpad.net/tabbott/zulip/ubuntu',
    release     => 'trusty',
    repos       => 'main',
    key         => '84C2BE60E50E336456E4749CE84240474E26AE47',
    key_source  => 'https://zulip.com/dist/keys/zulip.asc',
    pin         => '995',
    include_src => true,
  }

apt::source クラスに値を設定する。

  file { "/etc/nginx/sites-available/zulip-enterprise":
    require => Package["nginx-full"],
    ensure => file,
    owner  => "root",
    group  => "root",
    mode => 644,
    source => "puppet:///modules/zulip/nginx/sites-available/zulip-enterprise",
    notify => Service["nginx"],
  }
  file { '/etc/nginx/sites-enabled/zulip-enterprise':
    require => Package["nginx-full"],
    ensure => 'link',
    target => '/etc/nginx/sites-available/zulip-enterprise',
    notify => Service["nginx"],
  }
  file { '/home/zulip/prod-static':
    ensure => 'directory',
    owner  => 'zulip',
    group  => 'zulip',
  }
  file { "/etc/cron.d/restart-zulip":
    ensure => file,
    owner  => "root",
    group  => "root",
    mode => 644,
    source => "puppet:///modules/zulip/cron.d/restart-zulip",
  }
  file { '/etc/postgresql/9.3/main/postgresql.conf.template':
    require => Package["postgresql-9.3"],
    ensure => file,
    owner  => "postgres",
    group  => "postgres",
    mode   => 644,
    source => "puppet:///modules/zulip/postgresql/postgresql.conf.template"
  }
  # We can't use the built-in $memorysize fact because it's a string with human-readable units
  $total_memory = regsubst(file('/proc/meminfo'), '^.*MemTotal:\s*(\d+) kB.*$', '\1', 'M') * 1024
  $half_memory = $total_memory / 2
  $half_memory_pages = $half_memory / 4096

  file {'/etc/sysctl.d/40-postgresql.conf':
    ensure => file,
    owner  => 'root',
    group  => 'root',
    mode   => 644,
    content =>
"kernel.shmall = $half_memory_pages
kernel.shmmax = $half_memory
# These are the defaults on newer kernels
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
"
    }

共有メモリとカーネルパラメータを設定する。

  exec { "sysctl_p":
    command   => "/sbin/sysctl -p /etc/sysctl.d/40-postgresql.conf",
    subscribe => File['/etc/sysctl.d/40-postgresql.conf'],
    refreshonly => true,
  }

カーネルパラメータを変更する。

  exec { 'pgtune':
    require => Package["pgtune"],
    # Let Postgres use half the memory on the machine
    command => "pgtune -T Web -M $half_memory -i /etc/postgresql/9.3/main/postgresql.conf.template -o /etc/postgresql/9.3/main/postgresql.conf",
    refreshonly => true,
    subscribe => File['/etc/postgresql/9.3/main/postgresql.conf.template']
  }

PGTune で PostgreSQL をチューニングする。マシンのメモリの半分を使用する。

  exec { 'pg_ctlcluster 9.3 main restart':
    require => Exec["sysctl_p"],
    refreshonly => true,
    subscribe => [ Exec['pgtune'], File['/etc/sysctl.d/40-postgresql.conf'] ]
  }
}

pgtune を実行する。

zulip/scripts/setup/configure-rabbitmq

#!/bin/sh -xe
#
# Delete the "guest" default user and replace it with a Zulip user
# with a real password

RMQPW=$("$(dirname "$0")/../../bin/get-django-setting" RABBITMQ_PASSWORD)
sudo rabbitmqctl delete_user zulip || true
sudo rabbitmqctl delete_user guest || true
sudo rabbitmqctl add_user zulip "$RMQPW"
sudo rabbitmqctl set_user_tags zulip administrator
sudo rabbitmqctl set_permissions -p / zulip '.*' '.*' '.*'

デフォルトユーザーを削除し、Zulip ユーザーに置き換える。

zulip/scripts/setup/initialize-database

#!/bin/bash -xe

# Change to root directory of the checkout that we're running from
cd "$(dirname "$0")/../.."

python manage.py checkconfig

python manage.py migrate --noinput
python manage.py createcachetable third_party_api_results

if ! python manage.py initialize_voyager_db; then
    set +x
    echo
    echo -e "\033[32mPopulating default database failed."
    echo "After you fix the problem, you will need to do the following before rerunning this:"
    echo "  * supervisorctl stop all # to stop all services that might be accessing the database"
    echo "  * scripts/setup/postgres-init-db # run as root to drop and re-create the database"
    echo -e "\033[0m"
    set -x
    exit 1
fi

supervisorctl restart all

echo "Congratulations!  You have successfully configured your Zulip database."
echo "If you haven't already, you should configure email in /etc/zulip/settings.py"
echo "And then you should now be able to visit your server over https and sign up using"
echo "an email address that ends with @ADMIN_DOMAIN (from your settings file)."
echo ""
echo "See README.prod.md for instructions on how to confirm your Zulip install is healthy, "
echo " change ADMIN_DOMAIN, debug common issues, and otherwise finish setting things up."

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10