サーバ初心者王がLaravel環境を構築するまでの道のり

# はじめに

普段、phpを書いてサーバサイドエンジニアを自称しているのですが、実はサーバについてなにもわかっていないことに気づきました。
NginxとかApacheを使っているってのはなんとなく知ってるけど、実際自分が書いたphpのコードがどのような技術の上であのWebページを表示しているのかってのが全くわかっていない。
おそらく、こういった「サーバ初心者王」は他にも一定数いらっしゃるんじゃないかと思います。

今回は、そんな「サーバ初心者王」がLravel環境の構築に至るまでの道中での出来事です。

## 使用したOSについて

Raspberry Pi 3が実家の押し入れの中で眠っていたので、今回はこいつを叩き起こして使うことにしました。

```bash
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
```

どうやらDebian系のようなので、「Raspberry Pi」で調べても出てこないことはUbuntuの記事を参考にしたりしました。

## 今回構築した環境

* Nginx

* php7.3

* MariaDB

* Laravel8

WebサーバをNginxにするかApacheにするかの選択は、以下の記事を参考にさせていただきました。

* [ApacheとNginxについて比較](https://qiita.com/kamihork/items/49e2a363da7d840a4149)

* [nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する](https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)

# Nginxのインストール

はじめに、WebサーバソフトウェアであるNginxをインストールしました。

```bash
$ sudo apt install nginx
```

ブラウザで、自身の（ラズパイの）IPアドレス（`http://{$privateIP}`）にアクセスすると「Welcome to nginx!」と問題なく表示されました。

## nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

`sudo nginx`、`sudo nginx -s stop`、`sudo systemctl start nginx`や、`sudo systemctl stop nginx`とコマンドの違いを気にせず、起動と停止をして遊んでいると、上記エラーが出ました。

上記エラーの確認は下記コマンドで行いました。

```bash
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Thu 2021-03-18 01:06:35 JST; 1min 2s ago
     Docs: man:nginx(8)
  Process: 11265 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 11266 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)

 3月 18 01:06:34 {$hostname} nginx[11266]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
# 以下略
```

[nginxを起動したら、起動に失敗しました。](https://teratail.com/questions/49145)によると、

> テストでsystemctl経由では無く、単独でnginxを動かしてしまっているなどが考えられます（同じnginxであっても、80番ポートをバインドできるのは、たった一つのプロセスのみです）

ということなので、80番ポートを確認してみました。
その後、該当プロセスをkillすると上記エラーが解決して、正常に起動・停止ができるようになりました。

```bash
$ sudo netstat -lntp
稼働中のインターネット接続 (サーバのみ)
Proto 受信-Q 送信-Q 内部アドレス            外部アドレス            状態        PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      4612/nginx: master
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      473/sshd
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      8446/cupsd
tcp6       0      0 :::80                   :::*                    LISTEN      4612/nginx: master
tcp6       0      0 :::22                   :::*                    LISTEN      473/sshd
tcp6       0      0 ::1:631                 :::*                    LISTEN      8446/cupsd

$ sudo kill 4612 # Nginx（80番ポートで稼働中のプロセス）のPID
```

調べた感じsystemctl経由の方が良さそうだったので、今後の起動・停止はsystemctl経由で行うことに統一しました。

# php-fpmのインストール

そもそも「php-fpmってなんなら？」と思っていたのですが、現在の私の理解では「動的にコンテンツを生成できないWebサーバプログラム（Nginx）が、動的にコンテンツを生成する外部プログラム（php）と連携するために必要な仕組み ＝ サーバがクライアントに動的コンテンツを提供できる」と捉えています。
つまり、Nginx上でphpを動作させるために必要なモノと理解しました。

php-fpmのインストールについて調べると、「phpとphp-fpm」、[php-fpmのみ」などインストール対象が異なる記事がたくさん出てきたので、それぞれどんなパッケージが追加されるか比べてみました。

```bash
# それぞれ必要箇所のみ抜粋
$ sudo apt install php7.3-fpm
以下のパッケージが新たにインストールされます:
  php-common php7.3-cli php7.3-common php7.3-fpm php7.3-json php7.3-opcache php7.3-readline

$ sudo apt install php7.3
以下のパッケージが新たにインストールされます:
  apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php7.3 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap php-common php7.3 php7.3-cli php7.3-common php7.3-json
  php7.3-opcache php7.3-readline
```

どうやら「php」をインストールすると、apacheなどの今回は必要ないパッケージも追加されるようだったので、`$ sudo apt install php7.3-fpm`のみ実行しました。

以下のコマンドで、phpとphp-fpmがインストールされていることを確認しました。

```bash
$ php -v
$ systemctl status php7.3-fpm.service
```

## php.iniのファイルパス

phpの設定ファイルであるphp.iniが「/etc/php/7.3/fpm/php.ini」と「/etc/php/7.3/cli/php.ini」と２つあって、中身も微妙に違ったので、最初は混乱しました。

```bash
$ php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/7.3/cli
Loaded Configuration File => /etc/php/7.3/cli/php.ini
```

上記コマンドを実行すると、どうも「/etc/php/7.3/cli/php.ini」が使われてそうだが、もう一方は「fpm/」って入っているしな、、と。

結論から言うと、後述の設定を経て`phpinfo();`の出力結果をみると、「/etc/php/7.3/fpm/php.ini」が参照されていることがわかりました。
当たり前といえば当たり前なのですが、上記コマンドはCLI（コマンドラインインターフェイス）上で実行したので、「cli/」である「/etc/php/7.3/cli/php.ini」が参照されていました。
少し「サーバ初心者王」すぎる感はありますが、スッキリして良かったです。

## Nginxとphp-fpmをつなぐ

php-fpmでは、FastCGIリクエストを受け付ける（Nginxと通信する）方法として、TCPソケットとUNIXドメインソケットがあるみたいです。
今回は、下記の記事を参考にして、UNIXドメインソケットを使用することにしました。

* [調べなきゃ寝れない！と調べたら余計に寝れなくなったソケットの話](https://qiita.com/kuni-nakaji/items/d11219e4ad7c74ece748)

### php-fpm側の設定

上記のUNIXドメインソケットを用いた通信を可能にするために、[php-fpm.conf のグローバル設定項目](https://www.php.net/manual/ja/install.fpm.configuration.php)の「プール一覧の項目」を設定していきました。

まず、php-fpmの設定ディレクトリの中身を確認しました。

```bash
$ ls /etc/php/7.3/fpm/
conf.d  php-fpm.conf  php.ini  pool.d
```

php-fpm.confの中身を見ると、プロセスプールの設定はpool.d/配下の.confファイルから読み込んでいることがわかりました。
つまり、「etc/php/7.3/fpm/pool.d/www\.conf」の内容がNginxとの通信設定に直結しているようでした。

そこで、ファイルの中身を確認してみました。

```bash
$ sudo nano /etc/php/7.3/fpm/pool.d/www.conf
# 一部抜粋
listen = /run/php/php7.3-fpm.sock  # ソケットファイルのパス
listen.owner = www-data            # アクセスを受け付けるユーザ = Nginxの実行ユーザ
listen.group = www-data            # アクセスを受け付けるユーザ = Nginxの実行ユーザ
```

次に、Nginxのワーカープロセスの実行ユーザが「www-data」であるかを確認しました。

```bash
$ ps aux | grep nginx
# 一部省略
root       497  0.0  0.2  50232  2312 ?        Ss    3月18   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   498  0.0  0.2  50376  2768 ?        S     3月18   0:00 nginx: worker process
www-data   499  0.0  0.2  50376  2772 ?        S     3月18   0:00 nginx: worker process
www-data   501  0.0  0.2  50376  2772 ?        S     3月18   0:00 nginx: worker process
www-data   502  0.0  0.2  50376  2744 ?        S     3月18   0:00 nginx: worker process
```

「www-data」であることがわかったので、そのままスルーしました。
結局、php-fpmの設定ファイルはなにも変更しませんでした。

### Nginx側の設定

Nginxの設定ファイルの記述方法が全くわからなかったので、下記の記事を参考にさせていただきました。

* [Nginx設定のまとめ](https://qiita.com/townsoft/items/3e2d410bbe65a364b603)

* [nginx連載3回目: nginxの設定、その1](https://heartbeats.jp/hbblog/2012/02/nginx03.html)

まず、Nginxの設定ディレクトリの中身を確認しました。

```bash
ls /etc/nginx/

conf.d        fastcgi_params  koi-win     modules-available  nginx.conf    scgi_params      sites-enabled  uwsgi_params
fastcgi.conf  koi-utf         mime.types  modules-enabled    proxy_params  sites-available  snippets       win-utf
```

上記ファイル（ディレクトリ）の中で、設定ファイルであるnginx.confに読み込まれているものを抜粋しました。

```bash
$ nano /etc/nginx/nginx.conf
# include文のみ、抜粋

# coreモジュールの設定
include /etc/nginx/modules-enabled/*.conf;

http {
        # MIMEタイプと拡張子の関連付け
        include /etc/nginx/mime.types;

        # バーチャルホストの設定
        include /etc/nginx/conf.d/*.conf;   # 中身無し
        include /etc/nginx/sites-enabled/*; # defaultファイルがある ←これをイジる
}
```

次に、php-fpmと通信を行うために、「/etc/nginx/sites-enabled/default」ファイルを編集しました。（「/etc/nginx/sites-available/default」と内容が同じだったので、バックアップを取らずにそのまま書き換えました）

```bash
$ sudo nano /etc/nginx/sites-enabled/default

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www;

        index index.php index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php7.3-fpm.sock; # /etc/php/7.3/fpm/pool.d/www.confのlisstenに指定してあるソケットを指定
        }
}
```

ちょっと気になったので、読み込まれているsnippets/fastcgi-php.confの中身を確認してみると、さらにその中でfastcgi.confが読み込まれていることがわかりました。

```bash
$ cat /etc/nginx/fastcgi.conf

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
```

どうやら、このfastcgi_paramの設定値が、phpの`$_SERVER`の値になるみたいです。これは「サーバ初心者王」としては、大きな発見でした。

最後に、access_logのフォーマットの指定と読み込むバーチャルホストを限定するためにnginx.confの編集を行いました。

```bash
$ sudo nano /etc/nginx/nginx.conf

        log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

        access_log /var/log/nginx/access.log main;

        # 中略

        # include /etc/nginx/conf.d/*.conf; # 必要ないのでコメントアウト
```

変更した設定を反映させるために、php-fpmとnginxを再起動しました。

```bash
$ sudo systemctl restart php7.3-fpm
$ sudo systemctl restart nginx
```

そして、公開ディレクトリ配下にindex.phpを作成しました。

```bash
$ sudo nano /var/www/index.php

<?php phpinfo(); ?>
```

`http://{$privateIP}`にアクセスすると、`phpinfo();`の内容が表示されることが確認できました。

# MySQL(MariaDB)のインストール

次にデータベースの準備をしました。
データベースの管理システムには、MySQLを採用することにしました。

```bash
$ sudo apt install default-mysql-server
# 一部抜粋
以下のパッケージが新たにインストールされます:
  default-mysql-server galera-3 gawk libcgi-fast-perl libcgi-pm-perl libconfig-inifiles-perl libdbd-mysql-perl
  libdbi-perl libencode-locale-perl libfcgi-perl libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl
  libhttp-date-perl libhttp-message-perl libio-html-perl liblwp-mediatypes-perl libreadline5 libsigsegv2
  libterm-readkey-perl libtimedate-perl liburi-perl mariadb-client-10.3 mariadb-client-core-10.3 mariadb-server-10.3
  mariadb-server-core-10.3 socat
```

どうやら、debian（buster）の標準データベースはMySQLではなくMariaDB（MySQL互換） になっているみたいなので、上記コマンドをそのまま実行しました。（`$ sudo apt install mariadb-server`と同じパッケージがインストールされる）

```bash
# インストールされたことの確認
$ mysql -V
mysql  Ver 15.1 Distrib 10.3.27-MariaDB, for debian-linux-gnueabihf (armv8l) using readline 5.2

$ mysqld -V
mysqld  Ver 10.3.27-MariaDB-0+deb10u1 for debian-linux-gnueabihf on armv8l (Raspbian 10)
```

## 初期設定

DBMSの初期設定として、rootのパスワードなどを設定するスクリプトを実行しました。

```bash
$ sudo mysql_secure_installation
  # 全部[y]で回答
```

しかし、パスワードを設定したにも関わらず、まだパスワード無しで入れてしまいました。
また、再度`$ sudo mysql_secure_installation`実行したときに聞かれる現在のパスワードを空で入力しても、何もエラーが出ませんでした。
再起動なども試したが、いっこうに反映されませんでした。
おかしく思い、いろいろ調べると下記の記事を見つけました。

* [技術メモの壁 Ubuntu 18.04 + MariaDB](https://fsck.jp/?p=793)

> 上記動作の原因は、初期状態の DB root ユーザ認証に unix_socket 認証プラグインが使われていることである。この状態では、DB root として接続するために OS の root 権限にならなければならない （sudo または su コマンドを使う）。OS root になっていれば、以下のようにパスワードなしで DB root として接続可能である。

そこでデータベースにログインして、unix_socket 認証プラグインが使われているかの確認を行いました。

```bash
# sudo mysql -u root でも sudo mysql -u root -p でもなんでも入れる
$ sudo mysql

MariaDB [(none)]> SELECT user,host,plugin from mysql.user;

+------+-----------+-------------+
| user | host      | plugin      |
+------+-----------+-------------+
| root | localhost | unix_socket |  # 確かに、unix_socket 認証プラグインが使われている
+------+-----------+-------------+
1 row in set (0.001 sec)
```

パスワード認証を採用するためにrootの認証方法を変える作戦で行こうかと思いましたが、下記の記事が見つかりました。

* [Ubuntu 20.04にMariaDBをインストールする方法](https://www.digitalocean.com/community/tutorials/how-to-install-mariadb-on-ubuntu-20-04-ja)

> Ubuntuでは、MariaDBのrootアカウントが自動システムメンテナンスと密接に結び付けられているため、そのアカウント用に設定された認証方法を変更してはいけません。変更したりすると、パッケージアップデートにより、管理アカウントへのアクセスが削除されることになり、データベースシステムが破損される可能性があります。

ということで、パスワード認証を採用する管理ユーザー（admin）を新たに作成することにしました。

```bash
# root権限を引き継いだadminユーザの作成
MariaDB [(none)]> GRANT ALL ON *.* TO 'admin'@'localhost' IDENTIFIED BY 'Your Password' WITH GRANT OPTION;

Query OK, 0 rows affected (0.001 sec)

# 権限の反映
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> SELECT user,host,plugin from mysql.user;
+-------+-----------+-------------+
| user  | host      | plugin      |
+-------+-----------+-------------+
| root  | localhost | unix_socket |
| admin | localhost |             |  # unix_socket 認証プラグインが使われていないユーザができた
+-------+-----------+-------------+
2 rows in set (0.001 sec)
```

作成したadminユーザでパスワード認証ログインができることを確認しました。

```bash
$ mysql -u admin -p
Enter password:

MariaDB [(none)]> SELECT USER();
+-----------------+
| USER()          |
+-----------------+
| admin@localhost |
+-----------------+
1 row in set (0.001 sec)
```

## laravelプロジェクト用のDB作成

パスワード認証ログインにこだわっていた理由は、LaravelからMariaDBに接続するときにパスワード認証ログインを使用するからです。

初期設定を終えると、laravelプロジェクト用のDBを作成しました。

```bash
# データベース一覧の表示
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.004 sec)

# 「laravel」というデータベースの作成
MariaDB [(none)]> CREATE DATABASE laravel;
Query OK, 1 row affected (0.001 sec)

# 作成されたことを確認
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel            |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.002 sec)
```

# Laravelのインストール

ようやく、Laravelのインストールまで来ました。
ながいながい「サーバ初心者王」の旅もこれで最終章です。

## composerのインストール

まず、Laravelをインストールするために必要なPHPのパッケージ管理システムであるcomposerをインストールしました。
今まで通りaptコマンドでインストールすることもできそうでしたが、[公式](https://getcomposer.org/download/)に倣ってphpコマンドでインストールすることにしました。

```bash
# インストーラをダウンロードする(phpコマンド以外にもcurlやwgetなどのコマンドでダウンロードもできるみたい)
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

# ダウンロードしたインストーラのハッシュをチェックし、正しければ'Installer verified'と表示する
$ php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

Installer verified

# インストーラを実行する
$ php composer-setup.php

All settings correct for using Composer
Downloading...

Composer (version 2.0.12) successfully installed to: {$Your Current Directory}/composer.phar
Use it: php composer.phar

# インストーラの削除
$ php -r "unlink('composer-setup.php');"

# composer.pharがインストールされていることの確認
$ ls
Desktop  composer.phar  ダウンロード  テンプレート  ドキュメント  ビデオ  音楽  画像  公開
```

このままだと、パスが通ってないのでグローバルにcomposerコマンドが実行できませんでした。（参考：[公式](https://getcomposer.org/doc/00-intro.md#globally)）

```bash
# インストールされたpharファイルをパスが通る場所にリネームして移動する
$ sudo mv composer.phar /usr/local/bin/composer

# composerコマンドがグローバルに使えることを確認
$ composer -V
Composer version 2.0.12 2021-04-01 10:14:59
```

## Laravelのインストール

composerでグローバルにLaravelのインストーラーをダウンロードしてから、`$ laravel new プロジェクト名`でプロジェクトを作成する方法もあるみたいですが、あまり汚したくないので下記コマンドでプロジェクト作成を行いました。

```bash
# homeディレクトリ配下にsrcディレクトリを作成
$ mkdir src

$ cd src

# 「laravel」というディレクトリを作成し、laravelプロジェクトを作成する
$ composer create-project laravel/laravel laravel
# 一部抜粋
# エラー発生
  Problem 1
    - laravel/framework[v8.12.0, ..., 8.x-dev] require ext-mbstring * -> it is missing from your system. Install or enable PHP's mbstring extension.
    - Root composer.json requires laravel/framework ^8.12 -> satisfiable by laravel/framework[v8.12.0, ..., 8.x-dev].
```

### it is missing from your system. Install or enable PHP's mbstring extension.

上記エラーが出て、laravelプロジェクトの作成に失敗しました。
どうやら、`mbstring`がないことが理由みたいなので、インストールしました。

```bash
$ sudo apt install php7.3-mbstring

# インストールされていることの確認
$ php --ini
# 一部抜粋
/etc/php/7.3/cli/conf.d/20-mbstring.ini,

# 再び、laravelプロジェクトを作成する
$ composer create-project laravel/laravel laravel
# 別のエラーが発生
    - phpunit/phpunit[9.3.3, ..., 9.5.x-dev] require ext-dom * -> it is missing from your system. Install or enable PHP's dom extension
```

今度は`dom`がないって怒られたので、同様にインストールしました。

```bash
# domを入れる → xmlを入れればdomも入ってくるみたい
$ sudo apt install php7.3-dom
# 一部抜粋
注意、'php7.3-dom' の代わりに 'php7.3-xml' を選択します
以下のパッケージが新たにインストールされます:
  php7.3-xml

# できた！！
$ composer create-project laravel/laravel laravel
# 一部抜粋（かなり長い）
Package manifest generated successfully.
74 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan key:generate --ansi
Application key set successfully.
```

## Nginxの再設定

アクセスしたときにLaravelの画面が表示されるように、Nginxのドキュメントルートを作成したLaravelプロジェクトに向けました。

```bash
$ sudo nano /etc/nginx/sites-enabled/default
    # 変更箇所のみ抜粋

        root {$home_dir}/src/laravel/public;

        index index.php;


# nginxを再起動して設定を反映
$ sudo systemctl restart nginx
```

### The stream or file "{$home_dir}/src/laravel/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

確認のため、`http://{$privateIP}`にアクセスすると、上記の権限エラーが出ました。
エラーの内容はNginxの実行ユーザにlaravel/storage/配下へのアクセス権限がないということなので、下記の権限設定を行いました。

```bash
# /etc/nginx/nginx.confのuser（www-data）にディレクトリの所有権を与える
$ sudo chown -R www-data:www-data ~/src/laravel/storage

# 権限を確認すると、755だったのでそのままにしておく
$ ls -l ~/src/laravel/storage
合計 12
drwxr-xr-x 3 www-data www-data 4096  5月 12 05:49 app
drwxr-xr-x 6 www-data www-data 4096  5月 12 05:49 framework
drwxr-xr-x 2 www-data www-data 4096  5月 12 05:49 logs
```

再び、`http://{$privateIP}`にアクセスすると、正常にLaravelの初期画面が表示されました。

## DBの接続設定

先ほど作成した「laravel」データベースと接続するために、laravelプロジェクトの.envファイルを編集しました。

```bash
$ nano ~/src/laravel/.env
# 一部抜粋
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=admin
DB_PASSWORD={$YourPassword}
```

DBの接続確認を行うために、laravelの対話シェルである「tinker」を起動して、簡単なSQL文を実行してみました。

```bash
# laravelプロジェクトのディレクトリに移動
$ cd ~/src/laravel/

$ php artisan tinker
>>> DB::select('select 1'); # テスト用のSQL文
Illuminate\Database\QueryException with message 'could not find driver (SQL: select 1)'
```

### Illuminate\Database\QueryException with message 'could not find driver (SQL: select 1)'

SQL文を実行してみると上記エラーが出たので、まだDBに接続できていないことがわかりました。
エラーの内容はドライバがないということなので、MySQLドライバをインストールしました。

```bash
$ sudo apt install php7.3-mysql

# 設定を反映させるためにNginxを再起動
$ sudo systemctl restart nginx

# 再びテストするとSQL文が通り、DBに接続できたことがわかった
$ php artisan tinker
>>> DB::select('select 1');

=> [
     {#3392
       +"1": 1,
     },
   ]
```

これで、ようやくLaravel環境の構築完了です。

# 結局必要だったパッケージ

時系列で書いていて、わかりにくいと思うので、最後に今回aptコマンドでインストールしたパッケージをまとめておきます。

```bash
$ sudo apt install nginx php7.3-fpm php7.3-mbstring php7.3-xml php7.3-mysql default-mysql-server
# 別途、composer, laravelのインストールが必要です
```

# さいごに

最後まで読んでくださった方、ありがとうございます。
いかがでしたか？「サーバ初心者王」の旅路は。
自分で一度手を動かしてみるというのは、やっぱり良いですね。今回の旅で「サーバ初心者王」から脱却できた気がします。

ただ、コード中の日時を見ていただくとわかるかと思いますが、途中疲れたりしてかなり日が空いています。やはり慣れない作業は難しいです。
これくらいの作業、半日あれば余裕で終わるっていうレベルにまで早く持って行って、早いこと「サーバ御家人」に昇格したいです。

最後に、なにか誤った解釈などございましたら、優しくご指摘お願いします。なにぶん、まだまだ未熟な「サーバ初心者キング」なもんで。