はじめに
インストール手順に従ってグループチャットアプリ Zulip をインストールして動かしてみました。が、マシンを再起動するとメッセージを送受信できなくなりました。何かが動いていないっぽい・・・README.prod.md によると、Zulip は下記のサービスを利用しているとのこと。
- postgresql
- rabbitmq-server
- nginx
- redis
- memcached
私は Zulip を AWS EC2 にインストールしたのですが、エラーログを読むと RabbitMQ の起動に失敗していました。ということで、インストールのスクリプトを読んで何がどのようにインストールされて動いているかを覚書にしていきます。
対象バージョンとインストール手順
リンク先のページを読んで Zulip 1.3.7 をインストールしました。
- Zulip 1.3.7
- Run your own Zulip server
- zulip/README.prod.md
インストールスクリプト
スクリプトは次の順序で実行されます。
- zulip/scripts/setup/install
- zulip/scripts/lib/install
- zulip/scripts/zulip-puppet-apply
- zulip/puppet/zulip/manifests/voyager.pp
- zulip/scripts/setup/configure-rabbitmq
- 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 に設定ファイルを書き込む。
[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) に書きます。
- zulip/puppet/zulip/manifests/base.pp
- zulip/puppet/zulip/manifests/app_frontend.pp
- zulip/puppet/zulip/manifests/postgres_appdb.pp
- zulip/puppet/zulip/manifests/redis.pp
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."