Laravelのサーバ環境構築について
今回、Laravel & BreezeでのAPIを作ってみました。
そのリリース環境で、いろいろと手間取ったので、備忘録としてまとめます。
環境情報
- CentOS 7.9
- php 8.1.20
- Laravel v10.13.2
- breeze v1.21.0
- NGINX
まずは失敗談
今回の実行環境は、もともと別なアプリケーションを動かしている都合上、WebサーバはNGINXを採用していました。
PHPやMySQL(MariaDB)は使っていないOSデフォルトの状態です。
まず、OSデフォルトのDBであるMariaDBをアンインストールし、MySQLをインストールとアプリ用のDB、ユーザの作成まで進めました。
PHPをアプリのローカル開発環境に合わせたバージョン(v8.0)で入れ直し、composerをインストール、そして過去経験からNGINXでPHPを動かすにはphp-fpmが必要と記憶していたためバージョンに対応するphp80-php-fpmをインストールしてNGINX向けの設定。
一方で、証明書を作成して、NGINXでphp-fpmを前提としたサイト設定を実施。
あとはローカル開発環境で作成していたAPIとフロントエンドをそれぞれ配置してmigrateやらcors設定、axiosの向き先設定、buildを行い、さて動作確認・・・となりました。
結果は散々
フロントエンドは動作OK。但し、そこからAPIに接続に行くとエラーになる。
ここからが、エラー原因の調査を試行錯誤。
CORSの設定を疑い、SANCTUM 周辺を疑い、APIではなく素のPHPファイルやLaravelアプリで試したり。
結果判明したことは、ローカル開発環境で作成したアプリはPHP 8.1.20だったのに対して、サーバーにインストールしたPHPのバージョンは8.0だったという事実。
正しい手順でやり直し
まずは現状のPHPをアンインストール
PHP(とその依存関係)についてインストールされている内容を確認する
yum list installed | grep php
コマンド実行結果では「php-opcache.x86_64」と「php80_php_opcache.x86_64」というようにphp80がついてるものとついてないものが混在している。バージョンも微妙に異なる。
php-fpmを停止させてアンインストールを試みる。
が、php-fpmのサービス停止でエラーになる。
状態を確認
system status php-fpm
このコマンドでもエラーになった。
php80と混在していることを疑い、php80側で状態を確認する
system status php80-php-fpm
こちらの結果は「active」になってる。こちらを停止する。
system stop php80-php-fpm
これでようやくPHPをアンインストールする
「PHP」と名のつくファイルを削除
yum remove php php_*
「php80」と名のつくファイルも削除
yum remove php80 php80_*
残存ファイルの確認
yum list installed | grep php
「gd3php.x86_64」と「onigruma5php.x86_64」が残っていたので、個別に削除する。
PHP 8.1をインストールする
環境が綺麗になったとみなしてPHP81をインストールする。
まずはインストール可能かを確認する。
既にRemiリポジトリは追加済みなので、そのままyumでインストールできる。
yum list | grep php81
次に念のためphp-fpmの残存がないか確認する。(/etc/php-fpm.dがないことを確認)
では、php81(と関連ファイル)をインストール
yum -y install php81 php81-php php81-php-json php81-php-mbstring php81-php-pdo php81-php-xml php81-php-fpm php81-php-mysqlnd php81-php-opcache --enablerepo=remi-php81
インストール結果を確認
yum list installed | grep php
php81のファイルだけがインストールされていることを確認。
(先の混在状態は何だったのか?)
「php」コマンドを有効化する
whitch php81
これでphp81の所在が出力される(今回は/usr/bin/php81)ので、そのシンボリックリンクを作成する。
ln -sf /usr/bin/php81 /usr/bin/php
これで「php」コマンドが使えるようになる。
バージョン確認をしてみる。
php -v
「8.1.21」と出力された。
php.iniを編集する。
php -i | grep php.ini
php.iniの所在を確認。(今回は /etc/opt/remi/php81)
参考までに以下の内容。
date.timezone = "Asia/Tokyo"
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.encoding_translation = Off
mbstring.detect_order = auto
mbstring.substitute_character = none;
mbstring.strict_detection = Off
php-fpmをサービス起動する。
sudo systemctl enable php81-php-fpm
sudo systemctl start php81-php-fpm
更に php-fpm.d/www,conf をNGINX向けに変更する。
今回は /etc/opt/remi/php81/php-fpm.d/www.conf を編集。
listen=/run/www.sock
user=nginx
group=nginx
listen.allowed_clients=127.0.0.1
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
pm = dynamic
userとかgroup、ownerはデフォルトはApacheだったりするので、今回はNGINXのユーザ/グループに変更。
1行目のlistenはソケットの作成先は環境毎に異なるので注意が必要。(最初は参考にしたネット情報のまま記載したけど、この後のphp81-php-fpmサービス再起動でエラーが出て調べたら、そんなパスはなかったので書き換えた)
www.confを書き換えたら、サービスを再起動。
sudo systemctl restart php81-php-fpm
NGINXのconfも php81-php-fpm に合わせて書き換える。
(php-fpm用に以下のような記述を入れる)
location ~* \.php$ {
try_files $uri /index.php =404;
fastcgi_pass unix:/run/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
ポイントは fastcgi_pass に前述のソケットを指定すること。
confを変更したら、NGINXを再起動。
ここでサイトルートにテスト用の index.php を配置してブラウザから接続。
index.php はこんな感じ。
<? php phpinfo(); ?>
うまく表示された!
あとは元のAPI資源に置き換えて再度画面テストすると、今度は csrf-coolie は無事正常終了。
でも、その直後の regist が完了しても画面が遷移しない。
ネットワークで確認すると、/api/userで「401 Unauthorized」になっている。
念の為DBも確認すると、ユーザは登録されている。
BreezeかSANCTUMの周辺を疑う。
特に SANCTUM_STATEFUL_DOMAINS が怪しい。というのもフロントエンドのドメインという説明は見たが、サブドメインを含めるべきかどうかで悩んで、結果サブドメインは含めずに記述していた。
試しにサブドメインも記述してみる。
動いた!
ここからはアプリの動作確認をして無事正常性を確認できたので終了。
最後に
今回は初めてLaravel/BreezeでのAPIを作り、それをサーバにデプロイするところをやってみた。
通常はApacheを使うところでしょうが、何かとNGINXを使う傾向があり、今回もPHP & NGINXの組み合わせ。
今回はトライ&エラーで何とか完遂したものの、以下の部分はしっかり理解が必要だと痛感しました。
- PHP & NGINX の場合はPHP-FPMが必要 → PHP-FPMの役割
- 認証ライブラリとしてBreeze → そもそもSANCTUMとは何か
これはまたの機会に。