【2台構成で学ぶ】仮想環境でLAMP構築し、PHPからMySQLに接続成功するまでの手順まとめ

### 目的とゴールと前提条件
##### 目的:LANPサーバを構築する（ローカルで構築、外部公開なし）
##### ゴール：ブラウザからWEBサーバ（Apache）にアクセスし、PHPからDBサーバ（MySQL）に接続し、画面表示させる！（本番環境で使えるセキュリティレベルは意識していない）
##### 前提条件：仮想サーバを2台用意（1台はWEBサーバ用、もう1台はDBサーバ用）
※WEBサーバとDBサーバで疎通が取れていること、クライアントPCからも疎通が取れていること

### 全体の流れ（図解イメージ）
                 [ クライアントPC（ブラウザ） ]
                          |
                          | アクセス
                         ▼
              ┌────────────────────────────┐
                    Webサーバ（Apache + PHP）　　　　　　　　　　　　　 　
                    ・IP：192.168.1.101 
                    ・index.php 実行                                                                    
              └──────────┬─────────────────┘
                         │
                         │ PHPのmysqlで接続要求
                         ▼
              ┌────────────────────────────┐
                    DBサーバ（MySQL）     
                    ・IP：192.168.1.102    
                    ・データベース名：testdb 
                    ・ユーザー：webuser      
              └────────────────────────────┘
                         │
                         │接続できたら「MySQL接続成功！」を表示（ゴール！！）


### やること
◯WEBサーバ、DBサーバ共通設定項目
　1-1：ホスト名設定
　1-2：IP固定設定（例：192.168.1.101, 192.168.1.102）
　1-3：SELinux無効化 or setenforce 0

◯WEBサーバ設定項目
　2-1：PHP、Apacheのインストール
　2-2：httpdサービスの自動起動設定とサービス起動
　2-3：firewalledでhttp解放
　2-4：index.php作成

◯DBサーバ設定項目
　3-1：MySQLインストール
　3-2：mysqldサービスの自動起動設定とサービス起動
　3-3：firewalledでポート3306を解放
　3-4：SQL設定（パスワード設定、ユーザ作成、DB作成など）

◯ブラウザからWEBサーバにアクセスし、「MySQL接続成功！」が表示されれば成功！！

### 🟥設定手順
#### ◯WEBサーバ、DBサーバ共通
1-1：ホスト名設定（分かりやすくするために！必要なければスルー）
```
　# uname -n
```
現在のホスト名を確認
```
　# hostnamectl set-hostname ＜ホスト名＞　＃＜ホスト名＞例：WEB⇨web01 #DB⇨db01
```
プロンプトが返ってくること
```
　# uname -n
```
設定したホスト名になっていること

1-2：IP固定設定
設定前確認（現在の設定を確認する）
```
　　# ip a　（IPアドレスを確認）
　　# ip route　（GWアドレスを確認）
　　# nmcli con show ＜インターフェース＞ | grep ipv4.method　（DHCP設定か、静的になっているか確認）
    実行結果→manual：静的　auto：DHCP
```

設定変更 ＃＜IPアドレス＞例：WEB⇨192.168.1.101 #DB⇨192.168.1.102
```
　　# nmcli con mod ＜インターフェース＞ ipv4.addresses ＜設定するIPアドレス＞
　　⇨このNICに静的IPアドレスを割り当てる。
　　# nmcli con mod ＜インターフェース＞ ipv4.method manual
　　⇨DHCPではなく、手動で設定した静的IPアドレスを使うようにする。
　　# nmcli con mod ＜インターフェース＞ ipv4.gateway ＜設定するIPアドレス＞
 　　⇨gwの設定
　　# nmcli con mod ＜インターフェース＞ ipv4.dns 8.8.8.8
 　　⇨DNSサーバの設定
　　# nmcli con mod ＜インターフェース＞ connection.autoconnect yes
　　⇨サーバ再起動後も自動的にこのネットワーク設定を有効にする。
　　# nmcli con up ＜インターフェース＞
　　⇨変更したネットワーク設定をすぐに有効にして接続を開始する。
```
設定後確認（設定が変更されたことを確認する）
```
　　# ip a　（IPアドレスを確認）
　　# ip route　（GWアドレスを確認）
　　# nmcli con show ＜インターフェース＞ | grep ipv4.method　（manualになっていることを確認）
```

1-3：SELinux無効化 or setenforce 0（テスト環境では無効化推奨）
　Linuxのアクセス制御を管理する仕組み
（SELinuxの制限で表示されない場合があるため、今回はあらかじめ無効化しておく。）

設定前確認（現在の設定を確認する）
```
　　# getenforce
　　実行結果
　　Enforcing（有効） / Permissive（許可のみ） / Disabled（無効）
```
🔸 permissive：ログだけ記録して実際にはブロックしない（推奨）
🔸 disabled：完全に無効
　
設定変更
```
　・バックアップ取得 
　　# cp -p /etc/selinux/config /etc/selinux/config_backup

　・設定変更  
　　# vi /etc/selinux/config
　　※以下の設定値に変更
　　SELINUX=permissive

　・差分確認
　　# diff /etc/selinux/config /etc/selinux/config_backup
　　
　・設定反映（変更を有効にする）
　　# reboot

　・設定後確認（permissiveに変更されたことを確認する）
　　# getenforce
```


#### ◯Webサーバ側（Apache + PHP）で行うこと
2-1：PHP、Apacheインストール
```
　# dnf install -y httpd php php-mysqlnd
 （今回のゴールに最低限必要なもの。php関連の他モジュールは必要であれば追加でインストール）
```

2-2：自動起動設定とサービス起動
```
　・設定前確認（現在の設定を確認する）
　　# systemctl is-enabled httpd
　　# systemctl status httpd

　・設定変更
　　# systemctl enable httpd
　　# systemctl start httpd
　
　・設定後確認（設定が変更されたことを確認する）
　　# systemctl is-enabled httpd
　　# systemctl status httpd
```

2-3：firewalledでHTTP解放
```
　・設定前確認（現在の設定を確認する）
　　# firewall-cmd --list-all

　・設定変更
　　# firewall-cmd --add-service=http --permanent
　　# firewall-cmd --reload

　・設定後確認（設定が変更されたことを確認する）
　　# systemctl is-enabled httpd
　　# systemctl status httpd
```

2-4：index.php 作成
```
  　# vi /var/www/html/index.php
　　 =================================================================
　　<?php
　　$host = '＜DBサーバのIPアドレス＞';
　　$db   = 'testdb';
　　$user = 'webuser';
　　$pass = '＜パスワードを設定＞';

　　$conn = new mysqli($host, $user, $pass, $db);

　　if ($conn->connect_error) {
　　    die("接続失敗: " . $conn->connect_error);
　　}
　　echo "MySQL接続成功！";
　　?>
　　 =================================================================
```
 
####  ◯ DBサーバ側（MySQL）で行うこと
3-1：MySQLインストール
```
　# dnf install -y mysql-server
```

3-2：自動起動と起動
```
設定前確認（現在の設定を確認する）
　　# systemctl is-enabled mysqld
　　# systemctl status mysqld
```

設定変更
```
　　# systemctl enable mysqld
　　# systemctl start mysql
```

設定後確認（設定が変更されたことを確認する）
```
　　# systemctl is-enabled mysqld
　　# systemctl status mysqld
```

3-3：firewalledでポート3306を解放
設定前確認（現在の設定を確認する）
```
　　# firewall-cmd --list-all
```

設定変更
```
　　# firewall-cmd --add-port=3306/tcp --permanent
　　# firewall-cmd --reload
```

設定後確認（設定が変更されたことを確認する）
```
　　# firewall-cmd --list-all
```

3-4：SQL設定（パスワード設定、ユーザ作成、DB作成など）
セキュリティ設定
```
　　# mysql_secure_installation
　（実行するとMySQLのセキュリティを強化するための質問が続きます。以下に質問される内容と回答例を記載します。
　　和訳はだいぶはしょってるのと、設定背景を正確に知りたい場合は調べていただければと思います。。）
　　①secure enough. Would you like to setup VALIDATE PASSWORD component?
　　和訳：セキュリティ向上のために、この機能を設定しますか？
　　⇨y または Y を入力

　　②There are three levels of password validation policy:
　　和訳：どのくらい強力なパスワードを要求するか（強度レベルを聞かれている）
　　⇨0を入力
　　⇨8文字以上でパスワードを設定する

　　③Estimated strength of the password: 50
　　　Do you wish to continue with the password provided?
　　和訳：入力されたパスワードの強度は 50点 と推定されます。このパスワードで続けてもよろしいですか？
　　⇨y または Y を入力

　　④Remove anonymous users? 
　　和訳：匿名ユーザー（anonymous users）を削除しますか？
　　⇨y または Y を入力

　　⑤Disallow root login remotely? 
　　和訳：rootユーザーでのリモートログインを禁止しますか？
　　⇨y または Y を入力

　　⑥Remove test database and access to it?
　　和訳：テスト用データベースと、そのデータベースへのアクセス権を削除しますか？
　　⇨y または Y を入力

　　⑦Reload privilege tables now? 
　　和訳：限テーブルを今すぐ再読み込みしますか？
　　⇨y または Y を入力
```

テスト用ユーザーとDB作成
```
　　# mysql -u root -p
　　⇨先ほどのセキュリティ設定で指定したパスワードを入力する。

　　-- ① データベース作成
　　mysql> CREATE DATABASE testdb;

　　-- ② Webサーバからアクセス可能なユーザー作成
　　mysql> CREATE USER 'webuser'@'＜WEBサーバのIPアドレス＞' IDENTIFIED BY '＜index.php 作成時に設定したパスワード＞';

　　-- ③ 権限付与（testdb のすべてのテーブルに対して）
　　mysql> GRANT ALL PRIVILEGES ON testdb.* TO 'webuser'@'＜WEBサーバのIPアドレス＞';

　　-- ④ 設定反映
　　mysql> FLUSH PRIVILEGES;
```

ここまでできたらブラウザからWEBサーバにアクセスし、ゴールできたか確認する。
http://＜WEBサーバのIPアドレス＞/index.php
「MySQL接続成功！」と表示されたら成功！！お疲れ様でした！！！


##### ✳︎構築時トラブルメモ✳︎
```
　　1.dnfコマンド実行時にCurl error (6) で失敗する
　　原因：DNS未設定、GWの設定ミス
　　解決策：/etc/resolv.conf に nameserver 8.8.8.8 を記載、ip route でGW確認し修正

　　2.index.php 実行時に接続失敗
　　原因：index.phpに記載したパスワードと、mysqlで設定したパスワードが異なっていた。
　　解決策：phpのエラーログ（/var/log/php-fpm/error.log）を確認し、ユーザは存在するけど権限がない理由で接続できていないことを確認。
　　　　　　「ALTER USER 'webuser'@'＜設定するIPアドレス＞' IDENTIFIED BY 'password';」で再設定した。
```

##### 最後にまとめ

WEBサーバとDBサーバを分離することで、構成の役割やアクセス制御、またトラブル時の対応方法などの観点も学べた。
※Markdownを使いこなせてなかったりで読みにくい箇所や考慮漏れの部分も多々あり、拙い文章ですみません。改善していきます。。。