【AWS,EC2,AmazonLinux】bootstrapを使ってAWS/EC2でLAMPサーバを構築

#はじめに

Webサービスの開発/本番環境としてよく扱われる「LAMPサーバ」を構築する際に、最初にインストールしたり設定するものは自動化してしまおう！ということで、シェル/AWSの勉強も兼ねて、構築と設定をしたので、手順を紹介します。

※この後にWordpress用のWebserverを構築することを考えているので、LAMPサーバ最小の構成での設定ではありません。
※LAMPサーバ・・・Linux:OS、Apache:Webサーバ、Mysql:DB、PHP:プログラミング言語　それぞれの頭文字からとっていて、近年WEBサービスを開発するプラットフォームとしてよく扱われている。


#bootstrapとは

AWSのEC2を立ち上げる際に利用できる機能として、「bootstrap」というものがあり今回はこちらを活用していきたいと思います。bootstrapとは、インスタンスを起動する最初の一回だけ実行されるもので、最初に実行したいコマンドを事前にシェルで書いておいておくことで、初期設定やソフトのインストールを自動で行うことができます。

シェルでbootstrapを書く際の注意点
・　#!/bin/bashで始める
・　bootstrapで実行されるコマンドは全てrootユーザで実行されるのでsudoをつけない
・　ユーザのフィードバックを必要とするコマンドに気をつける(-yフラグの無いyum update等)

###今回作成したbootstrap用のシェルです。手順紹介のあとで各コマンドの解説をします。
```
#!/bin/bash
yum update -y
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sed -i -e "s/enabled = 1/enabled = 0/g" /etc/yum.repos.d/remi.repo
yum -y update --enablerepo=epel,remi,remi-php56
yum -y install --disablerepo=amzn-main --enablerepo=epel libwebp
yum -y install libmcrypt libtool-ltdl libtidy libXpm libtiff gd-last autoconf automake
yum -y install --enablerepo=remi,remi-php56 t1lib
yum -y install httpd mysql56-server
yum -y install --disablerepo=amzn-main --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysql php-phpunit-PHPUnit php-pecl-xdebug php-cli php-common php-pecl-redis php-gd php-fpm php-intl
service httpd start
chkconfig httpd on
service mysqld start
chkconfig mysqld on
groupadd www
usermod -a -G www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
```

##AWS マネジメントコンソールでの作業手順

###インスタンスの作成


EC2でインスタンスを立ち上げます。サービスからEC2を選択し、インスタンスの作成をクリックします。
![wp01.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/fe1553be-2eb8-6af9-afa5-1287a794316a.jpeg)


<br>
<br>

####AMI
AMIは今回はAmazonLinuxを選択します。

![wp02.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/9bf62c0a-9fd5-86f5-b82d-e5f93faab68f.jpeg)

<br>
<br>

####インスタンスタイプの選択
インスタンスタイプは無料枠のT2.microを利用します。最後に「次の手順インスタンスの詳細の設定」をクリックします。
![wp03.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/2cc4bf91-b7d2-01fa-19ea-c28992c86038.jpeg)

<br>
<br>

####インスタンスの詳細設定
インスタンスの詳細設定では用意しておいたbootstrapを仕込みます。画面下の方にある「高度な詳細」をクリックします。


![wp04.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/4c535fb0-ec39-8ad9-5638-05b837fac7bd.jpeg)


「テキストで」を選択し、準備したシェルをコピーして貼り付けます。ここに貼り付けたシェルがインスタンスの起動時に一度だけ実行されます。最後に「セキュリティグループの設定」をクリックします。


![wp05.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/989f1451-0e71-0c84-887f-7808e120412e.jpeg)

<br>
<br>

####セキュリティグループの設定
次にセキュリティグループの設定をします。AWSではファイアウォールのような接続の設定をマネジメントコンソール上で簡単に行えます。「新しいセキュリティグループを作成する」を選択し、任意のセキュリティグループ名に変更してください。今回はWebサービスなのでHTTPとHTTPSのルールを追加します。SSHの0.0.0.0/0は全開放という意味で、セキュリティ上よくありません。ご自身がSSH接続するIPアドレスのみを許可することを強くオススメします。最後に「確認と作成」をクリックします。

![wp06.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/bb7b3e0f-3d78-973f-7aa3-8d134ff4153b.jpeg)


<br>
<br>

####インスタンス作成の確認
確認して設定内容に間違いが無ければ「作成」をクリックしてください。

![wp07.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/de298a13-e8dc-2d18-e0ec-653cb76c8a75.jpeg)

<br>
<br>

####キーペアの設定
既にキーペアをお持ちの方は既存のものを使うことができます。今回は「新しいキーペアの作成」を選択し、任意キーペア名を設定しましょう。キーペアのダウンロードをクリックします。

![wp08.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/4cf39f36-7d35-c619-b853-82ed03785dfa.jpeg)

キーペアはサーバへSSH接続する際に使用しますので、安全な方法で無くならないようきちんと保管して起きましょう。ダウンロードが終わったら「インスタンスの作成」をクリックします。

![wp09.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/8a07fc28-495b-fe9e-d27e-bc9e0e2602d2.jpeg)


<br>
<br>

####作成ステータス
インスタンスのIDをクリックしインスタンスの作成状況を確認します。

![wp10.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/1a4cf203-af75-b789-4647-6252d16d2fce.jpeg)

◯で囲われた部分が「pending」だった場合は、作成中なのでもう少し待ちましょう。画面のように「running」になっていれば作成完了です。

![wp11.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/5e13c342-c0bf-87dc-7407-c75ab629807d.jpeg)

<br>
<br>


###ElasticIPの設定

左側のメニューからElasticIPを選択します。ElasticIPではインスタンスのIPアドレスを固定することが出来ます。

![wp16.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/a38bf206-cc56-d581-6da8-a1f33d30aa12.jpeg)

新しいアドレスの割り当てをクリック。

![wp17.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/e42b49cc-ef9e-ebe6-10da-44692c965276.jpeg)

割り当てをクリック。

![wp18.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/1cef3432-9b2b-ac9b-0b86-f5bfd8999f17.jpeg)

成功していることが確認できたら、閉じるをクリックします。

![wp19.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/90cb2b06-3be5-6a44-cf9c-213b29d768a3.jpeg)

今割り当てたIPアドレスを右クリックし、「アドレスの関連付け」をクリックします。

![wp20.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/17c23121-da9f-0e6d-4a74-55e4e0c3a5a3.jpeg)

今回作成したインスタンスIDを指定します。次に、「関連付け」をクリックします。

![wp21.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/bb1f64ac-e285-1da2-638a-399e72cf3a77.jpeg)

関連付けできたことが確認できたら、「閉じる」をクリックします。

![wp22.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/cb7fe628-c109-19cd-7993-4e1fff0de049.jpeg)

###サーバにSSH接続

bootstrapが正しく実行されたかを確認するために、teratermでSSH接続します。固定したIPを入力し、「OK」をクリックします。

![wp23.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/ea4474ee-f09c-7872-9969-cba31fd61489.jpeg)

AmazonLinuxを指定すると、デフォルトのユーザがec2-userとなっているのでユーザ名にはec2-userと入力します。前の手順でキーペアを作成しダウンロードした秘密鍵でログインします。鍵を使うを選択し、「秘密鍵」をクリックします。

![wp24.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/c1f8ce9b-e291-3607-bfc1-82f26f48799e.jpeg)

移動していなければダウンロードフォルダに入ってるはずです。右下の「すべてのファイル」にしないと表示されないので注意してください。秘密鍵ファイルを選択したら、「開く」をクリックします。

![wp25.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/b10904ab-ea96-1b5b-6f97-aff07ff0d58d.jpeg)

「OK」をクリック。

![wp26.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/4bfb263d-74f8-7237-df96-31e25eef9057.jpeg)


#bootstrapで書いたコマンドの解説と確認

1.パッケージのアップデート。

```
# yum update -y
```

2.remiリポジトリの追加

remiリポジトリはAmazonLinuxではデフォルトでインストールされていないため、追加します。remiリポジトリを追加することで、yumリポジトリで管理されていない新しいバージョンのパッケージをインストールできるようになります。今回はphp-gdのインストールが将来wordpressの管理画面での設定で必要になるということで、シェルに追加しました。単純なLAMPサーバを立ち上げる際に必須なコマンドではありません。

インストールすると/etc/yum.repos.d/remi.repoというファイルが生成されます。
ファイルの中身を見ると、デフォルトでは全てenabled = 0という設定になっていて、phpなどをインストールする際のyumのコマンドのオプションで--enablerepo=remi という形で一時的にenabled = 1の状態にして使用した方が毎回enabled = 1の状態であるよりかはなにかあった時の問題の切り分けがしやすいと思うのでそういう設定にしました。
2つ目（sedコマンド）は行わなくてもいいですが、明示的に enabled = 0 にしたければおこなってください。

```
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# sed -i -e "s/enabled = 1/enabled = 0/g" /etc/yum.repos.d/remi.repo
```

3.各リポジトリのアップデート

```
# yum -y update --enablerepo=epel,remi,remi-php56
```

4.t1libのインストール

新しいバージョンの php-gd をインストールする場合、先に remi の gd-last と t1lib をインストールから、 php-gd をインストールしないと依存関係により php-gd インストールできなくなります。
amzn-main リポジトリは Amazon Linux の場合に存在するリポジトリなので、OS が Amazon Linuxでない場合には --disablerepo=amzn-main のオプションは外しましょう。

```
# yum -y install --disablerepo=amzn-main --enablerepo=epel libwebp
# yum -y install libmcrypt libtool-ltdl libtidy libXpm libtiff gd-last autoconf automake
# yum -y install --enablerepo=remi,remi-php56 t1lib
```

5.Apache、Mysqlのインストール

```
# yum -y install httpd mysql56-server
```

6.PHP5.6関連のインストール

```
# yum -y install --disablerepo=amzn-main --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysql php-phpunit-PHPUnit php-pecl-xdebug php-cli php-common php-pecl-redis php-gd php-fpm php-intl
```

7.Apache、Mysqlの起動と自動起動設定

```
# service httpd start
# chkconfig httpd on
# service mysqld start
# chkconfig mysqld on
```

8.グループの作成と、パーミッション設定

・ec2-userがファイルを操作できるようにする
・wwwグループを作成
・wwwグループに/var/wwwディレクトリの所有権を付与し、書き込みを許可
wwwグループの任意のメンバーはウェブサーバーに対してファイルの追加削除変更が可能となる。

wwwグループをインスタンスに追加

```
# groupadd www
```

ec2-userをwwwグループに追加

```
# usermod -a -G www ec2-user
```

/var/とそのコンテンツの所有権をwwwグループに変更

```
# chown -R root:www /var/www
```

/var/wwwおよびそのサブディレクトリ許可を変更し、グループの書き込みの許可を設定し、将来のサブディレクトリにグループIDを設定する

```
# chmod 2775 /var/www
# find /var/www -type d -exec chmod 2775 {} \;
```

/var/www およびそのサブディレクトリのファイル許可を繰り返し変更してグループの書き込み許可を追加します。

```
# find /var/www -type f -exec chmod 0664 {} \;
```


9.LAMPウェブサーバーのテスト用のファイル作成

ApacheドキュメントルートでシンプルなPHPファイルを作成する

```
# echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
```

ここまでがシェルの中身の解説になります。


#bootstrapのコマンドが正しく実行されたか確認する方法

###1.インストール済パッケージ一覧の表示
件数が多いのでgrepで名前指定して実行するのもオススメです。

```
# yum list installed
```

###2.Apache,Mysqlの起動確認

```
# service httpd status
# service mysqld status
```

###3.Apachetestpageの確認

インスタンスのIPadorress、XXX.XX.XX.XXXをブラウザに入力し下画像のようなテストページが表示されればOKです。

![sh01.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/0910616a-8ac1-0dee-b5aa-03ce3b2b4294.jpeg)


###4.PHPページの確認

インスタンスのIPaddress、XXX.XX.XX.XXX/phpinfo.phpをブラウザに入力し、下画像のようなPHP情報ページが表示されればOKです。

![sh02.jpg](https://qiita-image-store.s3.amazonaws.com/0/148264/cf640dde-489a-6959-0aaa-0ff2c9c30c7e.jpeg)


確認ができたらセキュリティ上の理由からphpinfo.phpファイルを削除します。

```
# rm /var/www/html/phpinfo.php
```



##Mysqlサーバーのセキュリティ保護
MySQL サーバーのデフォルトのインストールには、テストおよび開発に役立ついくつかの機能がありますが、実稼働サーバーでは無効にするか削除する必要があるようです。mysql_secure_installation コマンドを使用すると、ルートパスワードを設定し、安全でない機能をインストールから削除する手順が案内されます。
Mysqlの設定はパスワードの設定やYES/NOの応答など、ユーザが書き込む内容あるため自動化は出来ません。

###1.Mysqlの起動

```
# service mysqld start
```

###2.mysql_secure_installation を実行する

```
# mysql_secure_installation
```

プロンプトが表示されたら、root アカウントのパスワードを入力します。

現在の root パスワードを入力します。デフォルトでは、root アカウントにはパスワードが設定されていないので、Enter を押します。

```
Enter current password for root (enter for none):
```


####「Y」と入力してパスワードを設定し、安全なパスワードを 2 回入力します。安全なパスワード作成の詳細については、http://www.pctools.com/guides/password/ を参照してください。このパスワードは必ず安全な場所に保管します。

```
Set root password? [Y/n] Y
New password:
Re-enter new password:
```

####「Y」と入力して匿名ユーザーアカウントを削除します。

```
Remove anonymous users? [Y/n] Y
 ... Success!
```

####「Y」と入力して root ログインを無効にします。

```
Disallow root login remotely? [Y/n] Y
 ... Success!
```

####「Y」と入力してテストデータベースを削除します。

```
Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!
```

####「Y」と入力して権限テーブルを再ロードし、変更を保存します。

```
Reload privilege tables now? [Y/n] Y
 ... Success!
```

以上で作業は終了です、お疲れ様でした！

#まとめ
LAMPサーバの構築に必要な初期構築部分をBootstrapを用いることで、自動化することができました。実行者にYes/No等の「入力を要求されるコマンド」はBootstrapにいれることは出来ないので注意が必要です。
Bootstrapを設定しておけば同じようなLAMPサーバをAWSで複製する時に、同じ設定をする必要がなくなります。EC2マネジメントコンソールから数クリックで、自動化部分の設定が終了した同じ構成のインスタンスが作成できて非常に便利です。
今後は、Ansible , teraform を使って今回出来なかったところまで自動化してみたいです。