laravel で作ったサービスをサーバー移行する話

個人で、laravelで作った小さなwebサイトを持っているのですが、
諸事情により載せている某サーバーから移行する必要
（決してネガティブな理由ではないが諸事情によりサービス名を言えない）が出てきたので
今回移行した作業ログを残そうと思います。

#学び/思ったこと
* /var/www/html はOSインストール時にできるディレクトリだと思ってたがwebサーバーがインストールされたときに作成される
* locahostに対して通信するのと、IP直叩きで通信するのは名前解決までの挙動が違う。詳しくはループバックインタフェースについて調べる。（http://e-words.jp/w/ループバックアドレス.html)
* composerが神。なかったら多分死んでた
* ミドルウェアの変更は面倒だが、いつやるのがいいのか不明
    * 今回mysql、apacheのバージョンを変更しましたがそれによって一瞬動かなくなったものもあった
    * とんでもない脆弱性が見つかるか、こんなことでもないと見直すタイミングないのでは
    * ミドルウェア周りはdockerとかでまずテストするのがいいのかな
* 個人のサービスで小さくてもansibleとかchef用意したほうがいいのかなとちょっと思った

##前提
* サービスはlaravel5.1で動いている
* サービスは一部のページについては動的にDBから情報を引いて作成される
* git（bitbucket）で管理されている
* chef とか ansibleなんてものはない！！！！

##ハマったポイント
###/var/www/html がない
本番サーバーでは/var/www/html/ にサービスを配置していたので特に何も考えず配置をしようと思い
gitをまず入れ、apacheを入れる前にcloneしようと思ったのですが、該当のディレクトリがありませんでした。
apacheを入れることで該当のディレクトリが作成されました。
###centos5と7の違い
詳しくは以下リンクに譲りますが、結構変わってます。
http://qiita.com/sion_cojp/items/115e1671fcbc8f214aee

（serviceとsystemctl変える必要ある？）

###mysql5.7で コマンドの実行ができない
以下サイトによるとmysql5.7では初回インストール時にテンポラリのPasswordがrootに設定されるようです。
http://weblabo.oscasierra.net/installing-mysql57-centos7-yum/
もろもろのコマンドはrootユーザーのPasswordを変更しないと実行ができないようなのですが、
Passwordの変更をupdateで変更してももろもろのコマンドは動きませんでした。
正しくはalterで変更するみたいです。

ただだめなだけじゃなくて、実際ログイン時のPasswordは変更されるのでちょっとハマりました。
alterコマンドで変更しないとmysql的には変更されたことが検知されないのかな。

###mysql5.7で group by ができない
サイトのデータ移行が完了し、動作確認をしたところ
一部のページで以下のエラーが。

```
which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
```
どうやら適当にgroupbyを使ってると怒られる様になったみたいです。
http://qiita.com/nagi244/items/04747f8e4ec351b22311

とりあえず今回は`only_full_group_by`を無効にし事なきを得ましたが、あまり良くなさそうです。

#作業ログ
##やる必要があると思っていたざっくり作業（前日まで）
* サーバーの用意
* gitの用意
* gitからサービスを落としてくる
* サーバー環境の構築
 * mysqlインストール
 * mysqlユーザーの作成
 * 開発用のユーザー作成
* composer update
* apacheのインストール
	* これを期にnginxにする？
* apacheのDocumentRoot指定
* apache起動
* 動作確認→終わり

#実際にやった作業
##サーバーの用意
conohaの一番安いプランにしました。
（GMOと自分は一切の利害関係がありません）
さくらのvpsを一台持っていたのでさくらにしようとも思いましたが、
さくらってスケールアップ/ダウンできないんですね。
値段もconohaのほうが安いのでconohaをにしました
接続許可ポートというのがファイアウォールなのかどうかだけわからなかったのですが、
ファイアウォールだと想定して設定しました
OSはcent7
##開発ユーザの用意
`useradd username`
`passwd password`
sudo コマンドを許可する
以下を参考に`visudo`コマンドで最下部に追記
http://linuxserver.jp/linux/sudo%E3%81%A7%E4%B8%80%E8%88%AC%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%A7%E3%82%82root%E6%A8%A9%E9%99%90%E3%81%A7%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C

##git のインストール
以下の作業はrootで実行しました。

参考サイト
http://www.task-notes.com/entry/20150622/1434942000

`yum install git`
2017/3/26 では1.8.3.1がyumの最新みたいです。

```
git --version
git version 1.8.3.1
```

```
cd /usr/local/src
git clone git://git.kernel.org/pub/scm/git/git.git
cd git
make prefix=/usr/local all
```
以下のエラーが出たので調べる
`/bin/sh: cc: コマンドが見つかりません`

参考サイト
http://dqn.sakusakutto.jp/2012/10/centos6git18.html

```
sudo yum install make curl-devel gcc openssl-devel expat-devel  cpan
sudo yum install gettext  asciidoc xmlto
```

もう一度makeの実行
`make prefix=/usr/local all`

動いているけどversionが変わらない

```
git --version
git version 1.8.3.1
```
`yum remove git`をしてもう一度makeしてみるとgitがなくなるだけ

作業ログ振り返りると、gitがインストールされたディレクトリが、
yumによる場所とgitのmakeされた場所が違ったので、aliasを設定する。

参考サイト
http://webkaru.net/linux/alias-command/

```
vi ~/.bashrc
alias git='/usr/local/src/git/git'　を追記
source ~/.bashrc
```

gitが使えるようになりました。

```
git --version
git version 2.12.GIT
```

同じことを開発用に用意したユーザーにも行わないと開発ユーザーからgitが参照できません。

##apacheのインストール
/var/www/html がなかったのでapacheをインストールしました。

nginxでも良かったけど、色々以前調べて動的に大量のサイトを生成するときはapacheに分があるという理解だったので
今回はapacheを入れました。

```
yum install httpd
ls /var/www/html/
```

##gitからサービスを落としてくる
```
git clone https://name@yourrepository.git
fatal: could not create work tree dir 'yourrepository': 許可がありません
```

となったのでまずはユーザー設定をします。

```
git config --global user.name "yourname"
git config --global user.email "youraddress@domain"
```
併せて/var/www/htmlを開発ユーザーの権限に変更します。
`chown -R username www`

```
ls -l
drwxr-xr-x   4 username  root 4096  3月 26 11:43 www
```
```
git clone https://name@yourrepository.git
warning: templates not found /usr/local/share/git-core/templates
fatal: Unable to find remote helper for 'https'
```
必要なパッケージが足りないようです。

参考サイト
http://qiita.com/a_ishidaaa/items/8bb63a625e8a89b21a12


`sudo yum install curl-devel expat-devel gettext-devel   openssl-devel zlib-devel`

git のディレクトリで以下を実行

```
make
make install
```

参考
http://stackoverflow.com/questions/8329485/unable-to-find-remote-helper-for-https-during-git-clone

`git clone`を実行するも以下のエラー

`fatal: unable to access '/root/etc/gitconfig': 許可がありません`
sudo をつけると解決（ただしgitでなぜsudoが必要になったのか不明）

`sudo git clone https://name@yourrepository.git`

##PHPインストール/composerインストール
###PHP
普通にyumでインストールすると5.4が入るのですが、
サービスで使っている殆どのコンポーネントが5.4ではcomposerインストールできなかったのと
本番サーバーではPHP5.6が動いていたので、流石に5.6をインストールしました。
以下を参考にそのままできました

参考サイト
http://qiita.com/koichi_amami/items/e97bc70e82e95ab99f55
###composer
参考サイト
http://weblabo.oscasierra.net/php-composer-centos-install/

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
mv composer.phar /usr/local/bin/composer
```


PHP5.6を入れたため特に問題なく`composer install`でモジュールのインストールが完了。
ここのバージョンについてはサービスの状況によって違うと思います。


##mysql のインストールと設定
```
yum install mysql mysql-devel mysql-server mysql-utilities
```
mysqlコマンドを実行するもmysqlを立ち上げる事ができませんでした

以下サイトを発見
http://weblabo.oscasierra.net/installing-mysql57-centos7-yum/

どうやらcent７だと普通にyumを使ってもインストールができない模様。
書いてるとおりにやってみた結果は以下です。

```
ps aux | grep "mysql"
mysql     9323  0.1 34.3 1119472 171724 ?      Sl   14:06   0:00 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
root      9442  0.0  0.1 112664   964 pts/2    R+   14:12   0:00 grep --color=auto mysql
```

上のリンクを補足しておくと、インストールされた後のテンポラリのパスワードは以下コマンドでわかります。
`grep "password" /var/log/mysqld.log `

以下サイトを参考に、一回rootで使うときはPasswordがいらない状態にしてmysqldump の投入。
終わったらまたオプションを消してPasswordでのログインを必須にしておきます。

参考
http://qiita.com/ksugawara61/items/d8d69b7d57a3afcef980

###データの移行
本当はユーザーを作って対象のテーブルへの権限を付けたかったのですが、
権限を付ける前に対象のDB+テーブルを作ったほうが良さそうだったのでまずDBの作成を行いました。

本番サーバーから`mysqldump`を使ってDBのダンプを行います。
gitにpushしておけばpullするだけでdumpファイルが届くので、DBを作成したあとそれを入れる
`mysql -u root DB < dump_db_20170326.sql `

###rootユーザーPasswordを変更する
インストール時に設定されたrootユーザーのテンポラリPasswordを変更します。

`mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'your-PASSWORD';`
これでOK

`You must reset your password using ALTER USER statement before executing this statement.`
のエラーが出るときは、Passwordを設定してないか、updateで変更していないか確認したほうがよいです。
以下のサイトを参考に最初は実行しました。
http://qiita.com/is0me/items/91a0af0342c307b94a16
たしかにログインPasswordは変更できましたが、そのあと記載のエラーで`show databases`コマンドすら動かなかったため
更に調べてALTERで変更したところ動きました。

###サービス用のユーザーを作成する

```
create user
    -> 'name'@'localhost' identified by 'hoge';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
```
Passwordの設定に制約ができた模様。
サービスで使うDBなので、サービスの.envを書き換えることも考えましたが、
localの設定も変更しなくてはいけないので、断念（めんどくさい）。
以下サイトを参考にPasswordの制限レベルを低くする
参考サイト
http://music431permemo.blogspot.jp/2016/01/mysql.html

```
create user
    -> 'name'@'localhost' identified by 'hoge';
Query OK, 0 rows affected (0.00 sec)
```
権限の付与
`grant all on DB.* to name@'localhost'`

追加したユーザーでmysqlに入り、DBのデータを参照できることを確認しOK

##動作確認
ここまで問題ないかを確認する（ここまで問題なければ普通はあとapacheの設定だけのはず）

```
php artisan serve
curl localhost:8000
```

curlコマンドでtopページのhtmlが吐き出されたのでOK

## apacheの設定
conohaの場合（？）ServerName がhost-xxx-xxx-xxx-xxx(IPアドレス)になっているので、IPアドレスに変更をする
また、DoumentRootをgit cloneしたディレクトリとして追加する

```
diff /etc/httpd/conf/httpd.conf{,.bk}
< #ServerName host-xxx-xxx-xxx-xxx
< ServerName xxx.xxx.xxx.xxx
356,362d353
< 
< <VirtualHost *:80>
<     DocumentRoot "/var/www/html/yourproject/public/"
<     <Directory "/var/www/html/yourproject/public/">
<         AllowOverride All
<     </Directory>
< </VirtualHost>
```

##ファイアウォールの設定（サイトを直接アクセスしたら見れなかった）
apacheの設定も終わったので、ブラウザからIPアドレス直叩きでサイトにアクセスしたところ、トップが表示されず。
参考サイト
https://teratail.com/questions/53543
先程確認に使ったのは以下コマンド
`curl localhost:8000`
どうやらlocalhostを指定するのと、IPアドレスを指定するのは名前解決の経路が違うため、別途ファイアウォールの設定が必要なようです。
`sudo firewall-cmd --permanent --zone=public --add-service=http`
`sudo firewall-cmd --permanent --zone=public --add-service=https`

参考サイト
http://www.server-memo.net/centos-settings/firewalld/firewalld.html

ドメイン指定でトップが見れるようになりOK

##mysqlが動かなかった
トップは見えたものの、一部ページで以下のエラー
```Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'DB.hoge_master.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by```
mysql5.7では適当にgroup byをすると動かなくなる模様。
sqlモードを変更して対応しました。
/etc/my.cnfからonly_full_group_byの設定がされている部分を削除してmysqlの再起動でOK
ただし非推奨のようですので、急ぎじゃないときは実行の見直しをしたほうがいいかもしれません。

##DNSの変更
最後にDNSを変更します。
お名前.comで管理している（GMOと自分は利害関係がありません）ので以下サイトを参考に変更。

参考
http://server-99.com/onamae-zone/

最初一番下のチェックボックスをつけないで設定を反映したところ、
サイトに繋がらなくなったため、もう一度今度はチェックボックスをつけて反映したら30分くらいでサイトが見える様になりました。

---
#終わりに
今日中にサーバー移行を終わらせないといけない事情があったため色々雑に作業しましたが、なんとか終わりました。
一部先輩エンジニアにこっそり質問したりしましたが、賞味7時間くらいでしょうか。
仕事でこの辺は自分でやらず、担当の人にお願いすることが多かったのでいい経験になったなという感じです。

特にlocal＋本番サーバー一台での開発だとイマイチピンときてませんでしたが、composer の威力に驚きました。
構成管理やinfra as a code といった話が盛り上がるのも理解できます。

また、作業ログとして残したので、抜け漏れとか見づらい部分が多少あると思います。
一部有用そうな部分や今後改修が必要な部分については改めてまとめて別の記事にするかもしれません。

以上です。