ISUCON7決勝のポータルアプリとベンチマーカーをビルドして動かす

ベンチ単体で動かせばええやんという話もあるだろうが、ポータルからやるほうが盛り上がりがあるのでポータルをセットアップした。
READMEがあっさりしていたので動かすまでやったことをメモしておく。あっさりしているとはいえ公開されているだけでありがたい。そして、(セットアップがちゃんとしていれば)ちゃんと動く。（改めて、運営お疲れ様でした）

# 環境セットアップ

ルートの[README.md](https://github.com/isucon/isucon7-final/blob/master/README.md)にあるとおりUbuntu 16.04 LTSを使う。そして、依存をシュッと入れる。

```bash
sudo apt update
sudo apt install -y mysql-server nginx
sudo apt install -y git curl libreadline-dev pkg-config autoconf automake build-essential libmysqlclient-dev \
	libssl-dev python3 python3-dev python3-venv openjdk-8-jdk-headless libxml2-dev libcurl4-openssl-dev \
    libxslt1-dev re2c bison libbz2-dev libreadline-dev libssl-dev gettext libgettextpo-dev libicu-dev \
	libmhash-dev libmcrypt-dev libgd-dev libtidy-dev libgmp-dev
```

ほか、makeを使うために`build-essential`が必要なので入れる。[^1]

```bash
sudo apt install -y build-essential
```

MySQLのrootのパスワードは空でよさげなので一旦そうした。
あとポータルを動かすためにはタイムゾーン情報が必要なので入れておく。(これはREADMEにないが、あるべきなのだろうか…?)

```bash
mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -uroot mysql
```

この他にgo周りが必要なので入れる。xbuildでgo 1.9.2を入れることになっているが、ビルドだるいしポータルとベンチマーカだけ動けばいいのでバイナリをそのまんま入れてしまおう。(手抜き)
ここから入手して入れる: https://golang.org/dl/

```bash
wget https://dl.google.com/go/go1.9.2.linux-amd64.tar.gz
tar zxvf go1.9.2.linux-amd64.tar.gz
sudo mv go1.9.2.linux-amd64 /usr/local/go
```

PATH/GOPATHを設定すれば下準備は完了。

```bash
sudo bash -c 'echo "export PATH=\$PATH:/usr/local/go/bin" > /etc/profile.d/golang.sh'
echo <<'EOD' >> ~/.profile
export GOPATH="$HOME/go"
export PATH="$GOPATH/bin:$PATH"
EOD
```

## ベンチマーカーのビルド

depが必要なので入れる。

```bash
go get -u github.com/golang/dep/cmd/dep
```

ビルドする。素直にmakeすればいい。
`update-staticfile.go` は必要なのかよくわかんないけどとりあえずやっとく。

```bash
cd ~/cco/bench
make ensure
go run update-staticfile.go
make
```

## ポータルのビルド

こっちはあREADMEがっさりしててちょっと苦労した。
gb、go-bindataを使っているとのことなので入れる。

```bash
go get -u github.com/constabulary/gb/...
go get -u github.com/jteeuwen/go-bindata/...
```

依存モジュールをインストールしてビルドする。
gbのプラグインとしてgb-vendorというやつがありこれを使っているようなのでそれで入れる。[^1]

```bash
cd ~/cco/portal
gb vendor restore
make build
```

# ポータルを起動する

ポータルを起動するとテンションが上がるのでポータルを動かす。

## env.shを用意する

いったん空でOK。

```bash
touch ~/env.sh
```

## portalディレクトリを移動する

ビルド済のportalの中身を `/home/ubuntu/portal` に移動する。

```bash
mv ~/cco/portal ~/portal
```

symlinkでも動いたかもしれない。

## DBをセットアップする

これは迷うことはないのでREADMEの通り。

```bash
cat <<'EOD' | sudo mysql -uroot
create user ubuntu@localhost identified by 'ubuntu';
grant all on *.* to ubuntu@localhost;
EOD
portal/db/init.sh
```

チームのインポートは本戦に出場できなかったチームはちょっといじくる必要がある。
以下のファイルをいい感じにしよう。どうすればいいかはきっと見れば雰囲気で分かる。

* `portal/data/isu7f-teams.tsv`
* `portal/data/isu7f-servers.tsv`

あとはインポートする。(これは実はまだ動かしていない)

```bash
portal/bin/import -dsn-base "ubuntu:ubuntu@(localhost)" -target teams < portal/data/isu7f-teams.tsv
portal/bin/import -dsn-base "ubuntu:ubuntu@(localhost)" -target servers < portal/data/isu7f-servers.tsv
```

## ポータル用にnginxを設定する

`files/portal.nginx.conf` が本体だが、SSLの設定が入っている。
頑張ってSSLの設定をしてもよしなのだが、練習用だしめんどいのでHTTPで受けられるようにしてしまう。
これで上書きする。

```bash
# Apply fix for very long server names
server_names_hash_bucket_size 128;

gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";

# portal.example.com
upstream portal.example.com {
  server 127.0.0.1:3333;
}
server {
  server_name _;
  listen 80;
  access_log /var/log/nginx/access.log vhost;
  client_max_body_size 100M;
  location / {
          proxy_pass http://portal.example.com;
  }
}
```

## ポータルを起動する

```bash
sudo cp files/portal.day* /etc/systemd/system/
sudo systemctl enable portal.day1
sudo systemctl start portal.day1
sudo journalctl -xu portal.day1 # 確認
```

IPを指定すればnginx経由でアクセスできるはず。
このままだと競技が始まってないのでアクセスできないよって感じのことをいわれる。

## 競技を開始状態に変更する

管理者権限でこじあければいい。

`/login` が実はアクセス可能なのでアクセスして管理用の9999のチームIDでログインする。これはREADMEに載ってるのでみるべし。
その後、 `/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/admin` にアクセスするとなにやらそれっぽい画面がでるので競技中にステータスを変更する。

再びトップページに移動するとそれっぽい画面が出てテンションが上がる。

# ベンチマーカーを起動する

ベンチマーカーを起動して動かす。
単体で動くほか、worker modeというやつがあり、それで起動することでportalと連携する仕組みっぽい。

## env.shをいじる

さきほど `isu7f-teams.tsv` と `isu7f-servers.tsv` ででっちあげたgroup nameを環境変数にいれてやる。

```bash
ISU7_GROUP_NAME=oniyanma
```

## benchディレクトリを移動する

ビルド済のbenchの中身を `/home/ubuntu/bench` に移動する。

```bash
mv ~/cco/bench ~/bench
```

symlinkでも動いたかもしれないが、疲れてきたのでmvする。

## bench.prod.service を書き換える

`https://portal.isu.k0y.org` になっているのをTLSを外しつつ先程ポータルにアクセスしたときのそれに変える。

## ベンチマーカーを起動する

あとはよいしょしたら動く。

```bash
sudo cp files/bench.prod.service /etc/systemd/system/
sudo systemctl enable bench.prod
sudo systemctl start bench.prod
sudo journalctl -xu bench.prod # 確認
```

これでポータルでenqueueしたらベンチマーカーが動いてくれるようになってさらにテンションが上がる。（はず）

実際に動かしたらまた追記する。

[^1]: pull-req: https://github.com/isucon/isucon7-final/pull/3