Laravelの本番環境を一から構築する

Laravelには「Homestead」と「Laradock」があり、簡単に開発環境を用意することができますが、これらを本番環境で使用することはできません。
この記事では、Laravelの実行環境を一から構築する手順を説明します。

# 使用ソフトウェア・バージョン
- Laravel 8.21.0
- PHP 8.0（PHP-FPM）
- Nginx 1.18.0
- MySQL 8.0.22
- Ubuntu 20.04

＊Dockerは使いません

# 参考にしたコード

**Homestead**はLaravel公式の開発環境ですが、Homesteadを構築するコードがGitHubで公開されています。

[laravel/settler](https://github.com/laravel/settler)

「**scripts/provision.sh**」に環境を構築するコードが記述されています。Homesteadは多様な環境に対応できるよう多くのパッケージをインストールしているため、このコードを参考に必要なものだけインストールするようにします。

# 実行手順

1．PHPのインストール
2．php.iniの設定
3．PHP-FPMユーザーの作成
4．PHP-FPMの設定
5．Nginxの設定
6．Composerのインストール
7．Laravelのインストール・設定
8．開発用ツールのインストール
9．Deployerのインストール

# 1．PHPのインストール
- ppa:ondrej/phpリポジトリをシステムに追加する
- PHP8（PHP-FPM）および拡張機能のインストール

## 最新のPHPをインストールする

まずPHPのバージョンを選定します。利用可能なもののうち最も新しいバージョンが好ましいですが、環境によっては最新のものが利用できない場合があります。

Ubuntu20.04（LTS）の場合、apt-get installでインストールできるバージョンはPHP7.4のため、現時点（2021年1月）で最新のPHP8がインストールできません。そのため、PPAを使ってインストールするようにします。

**PPA（Personal Package Archive）**は個人が管理している非公式のリポジトリです。最新のパッケージが使えますがアップデートの保証はないため、リポジトリの選定と扱いには気を付ける必要があります。PHPのインストールには以下のPPAを使います。

[ppa:ondrej/php](https://launchpad.net/~ondrej/+archive/ubuntu/php/)

このリポジトリは、Debianの開発者でありPHP5の頃からパッケージ管理を行っている人のもので、公式パッケージもこのリポジトリを採用していることから信頼できるリポジトリと言えます。

[ppa:ondrej/php開発者のページ](https://deb.sury.org/)

また、調べたところ<font color="Red">Ubuntu公式のPHPパッケージのリリースは1年ほど前でしたが（更新されていない）、PPAは1ヶ月程度でアップデートされています。</font>PPAの方がセキュリティパッチが更新される頻度が多いためより安全であると思われます。

**・ppa:ondrej/phpリポジトリをシステムに追加する**

```
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
```

## Laravelのサーバー要件

次にPHPをインストールしますが、まずは公式ホームページで**Laravel 8.×**のサーバー要件を確認します。

[Laravelのサーバー要件](https://laravel.com/docs/8.x/deployment)

- **PHP >= 7.3**
- **BCMath PHP Extension**
- Ctype PHP Extension
- Fileinfo PHP Extension
- JSON PHP Extension
- **Mbstring PHP Extension**
- OpenSSL PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- **XML PHP Extension**

太字の「BCMath」「Mbstring」「XML」以外はPHPをインストールすると有効になるため、PHPおよび3つの拡張機能をインストールすれば要件を満たすことができます。

**・PHP8（PHP-FPM）および拡張機能のインストール（ppa:ondrej/php）**

```
sudo apt-get install php8.0-fpm php8.0-bcmath php8.0-mbstring php8.0-xml php8.0-mysql php8.0-zip
```

php-fpmとLaravelに必要な3つの拡張機能およびMySQL拡張機能をインストールしています。php8.0-zipはLaravelのインストールで必要になります。

＊NginxではなくApacheを使う場合は「php8.0-fpm」ではなく「php8.0」をインストールしてください。Apacheおよび関連パッケージがインストールされます。

**php8.0-fpm**には以下のパッケージも含まれています。

php-common　php8.0-cli　php8.0-opache　php8.0-readline

これらはLaravelが動作する最低限の拡張機能であるため、必要になった時点で他のパッケージもインストールしましょう。上記で紹介した「laravel/settler」のprovision.shでは、どのような拡張機能を使用しているか確認することができます。またPHP開発者の新原さんのブログも参考になると思います。

[Shin x Blog](https://blog.shin1x1.com/entry/docker-shin1x1-php-dev)


# 2．php.iniの設定

- FPMとCLIのphp.iniを設定する
 
PHPの設定ファイルは以下の2つです。

- **/etc/php/8.0/fpm/php.ini（FPM）**
- **/etc/php/8.0/cli/php.ini（CLI）**

これらのファイルは本番用の推奨設定ファイルである以下と同じものです。

- /usr/lib/php/8.0/php.ini-production（FPM）
- /usr/lib/php/8.0/php.ini-production.cli（CLI）

**・FPMとCLIのphp.iniを設定する**

```
＊以下は「FPM」「CLI」両方の設定ファイルで変更

memory_limit = 512M
date.timezone =　"Asia/Tokyo"
mbstring.language = Japanese
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII　

＊以下は「FPM」の設定ファイルでのみ変更

upload_max_filesize = 100M
post_max_size = 100M
```

メモリの上限値やファイルの最大値はHomesteadで使用されている値ですので、環境に応じて適切な値を設定してください。

mbstring関係の設定ですが、php5.6以降で「mbstring.http_input」「mbstring.http_output」「mbstring.internal_encoding」は非推奨となったので設定しないようにしましょう。また、「mbstring.substitute_character」と「mbstring.encoding_translation」はデフォルトでオフになっているので明示的に指定する必要はありません。

[mbstring設定オプション](https://www.php.net/manual/ja/mbstring.configuration.php)

開発環境の場合はエラーを表示するように設定します。

```
error_reporting = E_ALL
display_errors = On
```

CLIの設定は「**php -i**」コマンド、FPMの設定は「**phpinfo();**」で確認できます。

# 3．PHP-FPMユーザーの作成

- 新規ユーザー作成
- デフォルトのパーミッション設定
- authorized_keysの設定
- デプロイディレクトリの作成

PHP-FPMをインストールするとデフォルトのユーザーである「www-data」が作成されます。このwww-dataまたはnginxユーザーを使用することもできますが、セキュリティ上好ましくないため新たにPHP-FPMユーザー（PHP実行ユーザー）を作成します。

PHP-FPMとNginxのユーザーおよびパーミッションについては以下の記事が参考になります。

[NGINX and PHP-FPM. What my permissions should be?](https://www.getpagespeed.com/server-setup/nginx-and-php-fpm-what-my-permissions-should-be)

**・新規ユーザーの作成**

```
sudo useradd phpuser
```

<font color="Red">このユーザーにはsudo権限は与えません。</font>また、第三者がファイルを操作できないよう「**.bashrc**」に以下を追記します。

**・デフォルトのパーミッション設定**

```
umask 0027
```

パーミッションは以下のようになります。

- ディレクトリ　750
- ファイル　640

SSHログインまたはdeployerを使う場合は認証が必要となるため、以下に公開鍵を設定しておきます。

**・authorized_keysの設定**

```
/home/phpuser/.ssh/authorized_keys
```

**・デプロイディレクトリの作成**

```
sudo mkdir /var/www/html
sudo chown phpuser:phpuser /var/www/html
sudo chmod 750 /var/www/html
```

デプロイ先は「/var/www/html」でなくても構いませんが、PHP-FPMユーザーを所有者としパーミッションを750に設定しましょう。


# 4．PHP-FPMの設定

- PHP-FPMの設定ファイルを編集する
- PHP-FPMを再起動する
 
新しく作成したユーザーをPHP-FPMのユーザーとして設定します。

**・PHP-FPMの設定ファイルを編集する**

```
sudo vi /etc/php/8.0/fpm/pool.d/www.conf

user = phpuser
group = phpuser
listen = /run/php/php8.0-fpm.sock　＊UNIXドメインソケット（デフォルトのまま）
listen.owner = phpuser　＊Unixドメインソケットを使う場合に設定が必要
listen.group = phpuser
```

UnixドメインソケットではなくTCP接続を行う場合は下記のように「IPアドレス：ポート番号」で設定します。

listen = 127.0.0.1:9000

**・PHP-FPMを再起動する**

```
sudo systemctl restart php8.0-fpm
```

# 5．Nginxの設定

- NginxユーザーにPHP-FPMグループを加える
- 設定ファイルを編集　/etc/nginx/conf.d/default.conf
- Nginxの再起動

＊Nginxは公式を参照してインストールしてください

[Nginxのインストール](https://nginx.org/en/linux_packages.html#Ubuntu)

**・NginxユーザーにPHP-FPMグループを加える**

```
sudo gpasswd -a nginx phpuser
```

これはNginxがPHP-FPMと通信を行う際にパーミッションエラーを起こさないようにするための措置です。

続いて、Laravel公式の設定例を参考にして設定ファイルを編集します。

[Laravel用のNginx設定](https://laravel.com/docs/8.x/deployment#nginx)

変更する箇所は以下になります。

**・設定ファイルを編集　/etc/nginx/conf.d/default.conf**

```
server_name localhost;　＊本番はドメイン名
root /home/ubuntu/laravel/public　＊開発環境
root /var/www/html/current/public;　＊本番環境（deployerを使う場合）
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
```

**rootディレクティブ**には、Laravelの公開ディレクトリ（public）のパスを指定します。上記はdeployerを使って「/var/www/html」にデプロイした場合のディレクトリになります。開発環境の場合はデフォルトユーザーであるubuntuのホームディレクリで良いかと思います。

**・Nginxの再起動**

```
sudo systemctl restart nginx
```

# 6．Composerのインストール

Composerは公式に参照してインストールしてください。

[Composerのインストール](https://getcomposer.org/doc/00-intro.md)

# 7．Laravelのインストール・設定

- Laravelのインストール
- 「.env」の編集
- config/database.phpの編集
- config/app.phpの編集
- 日本語ファイルのインストール

ユーザーUbuntuのホームディレクリでLaravelをインストールします。

**・Laravelのインストール**

```
composer create-project --prefer-dist laravel/laravel laravel（プロジェクト名）
```

バージョンを指定する場合は「laravel/laravel」の後に「＝」を付けて指定します。

例：laravel/laravel=8.4.0

「--prefer-dist」オプションはzipでダウンロードするので高速です。

以下のコマンドでインストールされたバージョンを確認します。

```
cd laravel
php artisan -V
```

インストール完了後「**.env**」「**config/databse.php**」「**config/app.php**」の3つの設定ファイルを編集します。

MySQLを使う場合は「.env」に以下を設定します。

**・「.env」の編集**

```
APP_ENV=production　＊本番用の設定
APP_DEBUG=false　＊（本番）デバッグ情報を表示しない
APP_URL=www.example.com

LOG_LEVEL=error　＊（本番）critical alert emergencyメッセージのみが出力される

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mysql　＊データベース名
DB_USERNAME=mysql-user
DB_PASSWORD=mysql-password
```

「.env」ファイルは機密情報を含みgit管理下に含まれないため、別途保存しておいてデプロイ時にコピーする必要があります。

データベースの設定ファイルは「.env」以外に「config/databse.php」があります。<font color="Red">このファイルは「.env」に値が設定されていない場合にのみ適用されます。</font>そのため、必要な箇所のみ変更します。

**・config/database.phpの編集**

```
'connections' => [
  'mysql' => [
    'collation' => 'utf8mb4_bin',
```

MySQLのcollation（照合順序）である「**utf8mb4_bin**」は、<font color="Red">大文字・小文字、ひらなが・カタカナ、絵文字などすべての文字を異なるものとして判定します。</font>日本語を使う場合に適したcollationです。

続いて、app.phpでタイムゾーンとロケールの設定を行います。

**・config/app.phpの編集**

```
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',　＊translationサービスプロバイダ―で使用される言語
'fallback_locale' => 'en',　＊デフォルトのロケールが利用できない場合に使用される言語
'faker_locale' => 'ja_JP',　＊fakerので使用される言語
```

**・日本語ファイルのインストール**

```
インストーラーのDL　php -r "copy('https://readouble.com/laravel/8.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
インストーラーの起動　php -f install-ja-lang.php
インストーラーの削除　php -r "unlink('install-ja-lang.php');"
```

上記を実行すると**resources/lang/ja**配下に日本語メッセージを含むファイルが作成されます。認証やバリデーションを行う際に日本語が出力されるようになります。

[ReadDouble 日本語ファイル](https://readouble.com/laravel/8.x/ja/auth-php.html)

開発環境であればlocalhostにアクセスするとLaravelのwelcomeページが表示されるはずです。

![laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283325/12af7ee7-2f14-07c9-15f3-12146aa0b95b.png)

# 8．開発用ツールのインストール

上記までで本番用の環境の構築は完成していますが、開発に便利なツールをインストールする方法も紹介しておきます。

- Telecscope（HTTPリクエスト解析）
- PHPStan　larastan（静的解析）
- PHP_CodeSniffer（コーディング規約）
- Laravel IDE Helper Generator（Docコメントの自動生成）

## Telecscope（HTTPリクエスト解析）

Telescopeは、リクエスト、ログ、データベース、キューなどを監視できる公式パッケージです。UIが優れておりAPI開発に役立ちます。似たようなツールとしてはlaravel-debugbarやclockworkといったものがあります。

**・Telescopeのインストールと設定**

```
composer require laravel/telescope --dev　＊本番でも使う場合は「--dev」オプションは除いてください
php artisan telescope:install
php artisan migrate
```

**・設定ファイル作成（config/telescope.php）**

```
php artisan vendor:publish --provider="Fruitcake\\TelescopeToolbar\\ToolbarServiceProvider"
```

開発のみで使用する場合、**config/app.php**からTelescopeのサービスプロバイダの登録を解除します。そして、App/Providers/AppServiceProviderのregisterメソッドに以下のように追記して手動でサービスプロバイダを登録する必要があります。

＊これはcomposerを利用した時にエラーを発生させないための措置です。

**・App/Providers/AppServiceProviderに追記**

```
    public function register()
    {
        if ($this->app->environment('local')) {
            $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
            $this->app->register(TelescopeServiceProvider::class);
        }
    }
```

また「--dev」オプションで開発用としてインストールした場合は**.envファイル**の設定を<font color="Red">「APP_ENV=local」</font>とします。

「localhost/telescope」にアクセスするとTelescope専用のページが表示されます。

![telescope-example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283325/62711c94-0abe-3231-c614-83fc200dd162.png)

詳細は公式を参照してください。

[Laravel Telescope](https://laravel.com/docs/8.x/telescope)

## PHPStan　larastan（静的解析）

PHPStanはPHPコードの静的解析を行うツールであり、larastanはLaravelのコードに最適化されたPHPStanのラッパーツールです。Laravelのコードの解析を行うには2つのツールをインストールする必要があります。

**PHPStanとlarastanのインストール**

```
composer require --dev phpstan/phpstan
composer require --dev nunomaduro/larastan
```

インストール後、larastanの設定ファイルとなる「**phpstan.neon**」をプロジェクトのルートディレクトリに配置します。

**・phpstan.neonの作成**

```
includes:
    - ./vendor/nunomaduro/larastan/extension.neon
parameters:
    paths:
        - app  # 解析の実行対象とするディレクトリ
    level: 5  # 解析レベル（0-8）「8」が最も厳しい
    ignoreErrors:
    #    - '#Unsafe usage of new static#'
    excludePaths:
    #    - ./*/*/FileToBeExcluded.php
    checkMissingIterableValueType: false
```

**・larastan（PHPStan）の実行**

```
./vendor/bin/phpstan analyse
```

[larastan](https://github.com/nunomaduro/larastan)

[PHPStan](https://phpstan.org/user-guide/getting-started)

## PHP_CodeSniffer（コーディング規約）

PHP_CodeSnifferはPHPのコーディング規約である**PSR-12**に則って、コードのチェック・修正を行ってくれるツールです。

[PSR-12](https://www.php-fig.org/psr/psr-12/)

**・PHP_CodeSnifferのインストール**

```
composer require --dev "squizlabs/php_codesniffer"
```

インストール後、プロジェクトのルートディレクトリに「phpcs.xml」という設定ファイルを作成します。

**・phpcs.xmlの作成**

```
<?xml version="1.0"?>
<ruleset name="PSR12/Laravel">
 <description>PSR12 for Laravel</description>

 <rule ref="PSR12">
  <!-- <exclude name="Generic.Files.LineLength.TooLong"/> 除外するルールの指定 -->
 </rule>

 <arg name="colors"/>
 <arg value="sp"/>

 <!-- <file>./app</file>　含めるディレクリの指定 -->
 <!-- <exclude-pattern>**/tests/**</exclude-pattern>　除外するディレクトリの指定 -->
</ruleset>
```

上記の設定はPSR-12を使ってコードのチェックを行う設定です。詳細は公式を参照してください。

[PHP_CodeSniffer設定ファイル](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset)

設定ファイルを作成すると、以下のコマンドでチェック・修正を行うことができます。

**コーディング規約のチェック実行**

```
./vendor/bin/phpcs
```

**修正候補との差分を表示**

```
./vendor/bin/phpcs --report=diff
```

**修正を実行**

```
./vendor/bin/phpcbf
```

[PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer)

## Laravel IDE Helper Generator（Docコメントの自動生成）

Laravel IDE Helper Generatorは、モデルのDocコメントを自動生成してくれます。

**・Laravel IDE Helper Generatorのインストール**

```
composer require --dev barryvdh/laravel-ide-helper
```

**・設定ファイル作成（config/ide-helper.php）**

```
php artisan vendor:publish --provider="Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider"
```

**・モデルのDocコメントを自動生成**

```
php artisan ide-helper:models　全モデルに対して実行
php artisan ide-helper:models "App\Models\User"　特定のモデルを指定
```

上記コマンドを実行すると、既存のファイルを上書きするか「_ide_helper_models.php」として新規作成するか質問されます。新規ファイルを作成し確認してから反映する方が安全です。

また、コマンドに「--writeオプション」を付与すると上書きされ、「--nowriteオプション」を付与すると新規ファイルが作成されます。

デフォルトでは大量のマジックメソッドが出力されるので、抑制したい場合は設定ファイルで以下の項目をfalseに変更します。

**・config/ide-helper.php**

```
'write_model_magic_where' => false,
```

モデルのDocコメント自動生成の他に、IDEによるFacadeのAutoCompletionを補完する機能もありますが、VSCodeではLaravelの拡張機能で補完されるので筆者はモデルのDocコメント生成のみに使用しています。

[Laravel IDE Helper Generator](https://github.com/barryvdh/laravel-ide-helper)

# 9．Deployerのインストール

Laravelをデプロイする際には、PHP製のDeployerがおすすめです。

**・Deployerのインストール**

```
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep
```

インストール後、プロジェクトのルートディレクトリで次のコマンドを実行すると、Laravel用の設定ファイル（deploy.php）が生成されます。

**・deploy.phpの作成**

```
dep init -t Laravel
```

**・deploy.phpの修正項目**

```
set('repository', '利用するリポジトリのURL');
set('composer_options', 'install --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader');　＊composer installでエラーが出るので「--no-suggest」オプションのみ外す設定
set('keep_releases', 2);　＊デプロイしたコードを2世代保持する設定
set('writable_mode', 'chmod');　＊chmodコマンドを使えるよう設定
host('www.example.com')
    ->forwardAgent()　＊SSH forwardAgentを使う場合の設定
    ->user('phpuser')
    ->set('deploy_path', '/var/www/html');  ＊デプロイ先のディレクトリ
task('change:mode', 'cd {{release_path}} && \　＊パーミッション変更
    find . -type f -perm 664 -exec chmod 640 {} + && \
    find . -type d -perm 775 -exec chmod 750 {} +');
after('deploy:vendors', 'change:mode');
```

Laravelの**.envファイル**は.gitignoreに含まれておりバージョン管理されないため、デプロイディレクトリにあらかじめコピーしておく必要があります。配置場所はデプロイディレクトリが「/var/www/html」の場合は「**/var/www/html/shared/.env**」となります。

sharedディレクトリは、各リリースからシンボリックリンクで参照される共有ディレクトリです。.envファイルの他にstorageディレクトリも共有されます。

deployerでデプロイするとパーミッションがディレクトリ（755）ファイル（664）となります。Laravelのファイルの中には実行権が設定されているものがあり、それを変更すると誤作動を起こす可能性があるため、664のファイルのみ抽出して640に変更しています。ディレクトリは750に変更しています。

**・デプロイの実行**

```
dep deploy -vvv（詳細を表示するオプション）
sudo chmod 400 /var/www/html/shared/.env
```

上記、Nginxの設定でも説明しましたが、公開ディレクトリの設定は以下のようになります。

**/etc/nginx/conf.d/default.conf**

```
root /var/www/html/current/public;
```

currentディレクトリはシンボリックリンクであり、Laravel本体は「/var/www/html/releases/」以下に配置されます。

[Deployer](https://deployer.org/docs/how-to-deploy-laravel.html)

# 終わりに

LaravelにはHomesteadやLaradockなど開発環境を簡単に用意できるものがありますが、一から構築するとなるとなかなか大変です。PHPパッケージのインストールやPHP-FPM/Nginxの設定など、まとまった情報がなかったので今回まとめて記事にしました。

これらの手順を毎回実行するのは煩雑なので、Ansible等を使うまたはスクリプト化して自動で行うことをお勧めします。環境構築の一助になれば幸いです。