はじめに
マネージドサーバー(KAGOYA、さくら、Xserverなどの専用プラン)では、セキュリティ上の理由から、ユーザー権限が厳格に管理されています。
「storageフォルダを 777 にすれば動く」という強引な解決策は、セキュリティリスクを高めるだけでなく、根本的な解決になりません。
この記事では、「正しい権限設定」 と 「パフォーマンスを引き出すPHP-FPM設定」 の2点に絞って解説します。
お知らせ(採用情報)
最後にお知らせとなりますが、AppTime では一緒に働くメンバーを募集しております。
詳しくは採用情報ページをご確認ください。
みなさまからのご応募をお待ちしております。
1. 権限問題の正体:なぜ「ログ出力」でエラーが出るのか
Laravelでは、storage と bootstrap/cache ディレクトリに対して、実行ユーザーが書き込み権限を持っている必要があります。
-
ブラウザからのアクセス: Webサーバーユーザー(例:
apacheまたはwww-data)が実行。 -
Artisanコマンド(SSH): ログインユーザー(例:
your-user)が実行。
一方がファイル(ログやキャッシュ)を作成すると、もう一方がそのファイルを更新・削除できなくなり、以下のようなエラーが発生します。
UnexpectedValueException: The stream or file ".../laravel.log" could not be opened
まず実行ユーザーを確認する
設定を変更する前に、Webサーバーが実際にどのユーザーで動いているか確認しましょう。
# PHP-FPMの設定ファイルを確認する
grep -E "^user|^group" /etc/php-fpm.d/www.conf
# 例: user = apache, group = apache
# または、Laravelから確認するワンライナー
php artisan tinker --execute="echo exec('whoami');"
解決策①:ACL(Access Control Lists)を利用する
chmod だけでは不十分な場合、ACL を使って「特定ユーザーに常に権限を与える」設定が推奨されます。
# Webサーバーユーザー(apacheまたはwww-data)に権限を付与
sudo setfacl -R -m u:apache:rwx storage bootstrap/cache
sudo setfacl -dR -m u:apache:rwx storage bootstrap/cache
# ログインユーザー自身にも権限を確保
sudo setfacl -R -m u:your-user:rwx storage bootstrap/cache
sudo setfacl -dR -m u:your-user:rwx storage bootstrap/cache
-d オプションにより、以降に新規作成されるファイル・ディレクトリにも自動でACLが継承されます。
ACLが使えない環境の場合:
ディストリビューションによってはaclパッケージのインストールが必要です。
また、/etc/fstabでマウントオプションにaclが含まれているか確認してください。
どうしても使えない場合は、後述の「解決策②」で対応できます。
2. Laravel側の「ログ設定」でエラーを回避する
権限設定をしても、新しいファイルが作成される際にデフォルトのパーミッションが原因で詰まることがあります。config/logging.php を修正して、作成されるログファイルの権限を指定しましょう。
// config/logging.php
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
'permission' => 0664, // グループメンバーも読み書き可能に(0666より安全)
],
0666vs0664について:
元のサンプルでは0666(全ユーザーが読み書き可能)が使われることがありますが、
Webサーバーユーザーとログインユーザーを同じグループに所属させた上で0664にする方が、セキュリティ上より好ましい設定です。
本番環境では/var/log/laravel/などを専用ディレクトリとして切り出し、グループ管理するとより堅牢です。
解決策②:グループを揃えてumaskで対応する(ACL非対応環境向け)
ACLが使えない場合は、WebサーバーユーザーとSSHログインユーザーを同じグループに所属させる方法が有効です。
# ログインユーザーをapacheグループに追加(要再ログイン)
sudo usermod -aG apache your-user
# storageをグループ書き込み可能にする
chmod -R 775 storage bootstrap/cache
chown -R your-user:apache storage bootstrap/cache
3. PHP-FPMの最適化:マネージド環境の性能を引き出す
マネージド専用サーバーなどの独立した環境では、PHP-FPMの設定をデフォルトから変更するだけで、レスポンス速度と同時接続数が大幅に改善します。
設定ファイルの場所を確認する
# メインの設定ファイルを探す(バージョン番号は環境に応じて変わります)
find /etc -name "www.conf" 2>/dev/null
# 例: /etc/php-fpm.d/www.conf
# /etc/php/8.2/fpm/pool.d/www.conf
pm(Process Manager)の選択
| モード | 特徴 | 適した環境 |
|---|---|---|
| static | プロセスを常駐させる。起動オーバーヘッドがなく最速。 | 専用サーバーでメモリに余裕がある場合 |
| dynamic | アクセス量に応じてプロセス数を増減させる。 | メモリを節約したい場合 |
| ondemand | リクエスト時のみプロセスを起動。最もメモリ効率が良い。 | アクセスが少ないサイト・ステージング環境 |
設定例(メモリ4GB程度の環境)
; --- static(専用サーバー推奨設定) ---
pm = static
; 最大プロセス数の目安: (サーバーメモリ - 他のミドルウェア使用分) / 1プロセスあたりのメモリ
; 1プロセスのメモリ消費は "ps aux | grep php-fpm" で確認可能(おおよそ40〜80MB)
pm.max_children = 40
; メモリリーク対策:一定数のリクエストを処理したらプロセスを再起動
pm.max_requests = 500
; --- dynamic(メモリ節約型設定) ---
pm = dynamic
pm.max_children = 20 ; プロセスの上限
pm.start_servers = 5 ; 起動時のプロセス数
pm.min_spare_servers = 3 ; 最小待機プロセス数
pm.max_spare_servers = 8 ; 最大待機プロセス数
pm.max_requests = 500
設定変更後の反映方法
設定を変更したら、 必ずPHP-FPMを再起動(またはリロード) してください。
# 設定の構文チェック(再起動前に必ず実行)
php-fpm -t
# PHP-FPMの再起動(環境・バージョンに応じてコマンドが変わります)
sudo systemctl restart php-fpm # CentOS/RHEL系
sudo systemctl restart php8.2-fpm # Ubuntu/Debian系(バージョン番号に注意)
# ダウンタイムを避けたい場合は graceful reload
sudo systemctl reload php-fpm
4. デプロイ時に忘れがちな「キャッシュのクリアと再生成」
権限や設定を変更した後は、必ず以下のコマンドでキャッシュを再生成します。この際、Webサーバーユーザーと同じ権限で実行するか、実行後に再度権限を確認してください。
# キャッシュをすべてクリアしてから再生成
php artisan config:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
まとめ
| 課題 | 推奨アプローチ |
|---|---|
| 権限エラー |
777 ではなく ACL または グループ管理 で複数ユーザーの共存を認める |
| ログエラー |
logging.php で permission を指定する(0664 推奨) |
| パフォーマンス | PHP-FPMの pm.max_children を環境に合わせて最適化する |
| デプロイ後の不整合 |
artisan cache:clear などで必ずキャッシュを再生成する |
これらを整えるだけで、Laravelの運用は驚くほど安定します。