Laravel4、app/storageのパーミッショントラブル

Tags : Laravel4  

Laravelやその他のフレームワークでも同様ですが、パーミッションを正しく指定しているはずなのに、ファイルキャッシュが書き込めないとかいう状況になることがあります。これは、Webサーバーの動作ユーザー/グループとLaravelをインストールしたユーザー/グループ(通常は皆さんのユーザー/グループでしょう)が異なることが原因です。

この問題はLaravelやPHPに限らず、Webサーバーの動作により作成するファイルに、ユーザーがコマンドでアクセスする場合、その逆にユーザーにより作成されたファイルに、Webサーバーから起動されたプログラムやスクリプトからアクセスする場合に起きるものです。そのため、根本的な解決には、サーバー設定とパーミッションの知識が必要となります。

とりあえず対処するならば、Laravelの場合、chmod -R 777 app/storageを毎回実行する方法もあります。しかし、これも面倒です。

解決する方法は、いくつかあります。

ファイル所有者の権限で実行する

最初に紹介するのはサーバーの設定を変更し、ファイル所有者(もしくは、指定したユーザー)としてアクセスを実行する方法です。いくつかWebサーバーの拡張機能を追加したり、設定ファイルを変更することになるでしょう。多人数がWebサーバーを使用する状況であれば、実運用サーバーに一番近い環境に変更する方法です。

基本的にWebサーバーは、Webサーバーの設定ファイルで指定されたユーザー/グループで動作します。ですが、実行するファイルのユーザー/グループで実行する仕組みも持っています。

もし、今までWebアクセスやArtisanコマンドの実行時に、app/storage下のファイルに関して、パーミッションのエラーを起こしたことがないのであれば、そのシステムは皆さんのユーザー/グループでWebからのアクセスを実行してくれている可能性が大きいでしょう。

その逆に、このようなパーミッションに関するエラーに出会っているのであれば、Webアクセスの結果として作成されたファイルは、Webサーバーの実行ユーザー/グループで作成され、皆さんがインストールやArtisanコマンド、Composerなどの実行により、直接的、間接的に作成されるファイルは皆さんのユーザー/グループで作成されます。通常、デフォルト状態のままでは、お互いにファイルのアクセス権がなく、パーミッションエラーが発生します。

簡単に確かめるには、Laravelを新しくインストールし、Webブラウザでルートにアクセスします。するとロゴが中央に表示されるデモページが表示されます。app/storage/sessions下にできているファイルのユーザーとグループを見てください。それがあなたのユーザー/グループと一致していれば、パーミッションの問題は起きません。Webサーバー、もしくはPHPはあなたのユーザー/グループとして動作しています。もし、wwwとか、wwwrun、www-user、www-data、nobodyのような、自分以外のユーザーの所有ファイルとなっていれば、Webサーバーは設定ファイルで指定されたユーザー/グループで動作しています。

このアクセス時にファイル所有者で実行する設定は、Webサーバーの種類や使用しているOS、PHPの動作モードなど、状況が多岐に渡るため、とても説明できません。一般的な方法ですのでWeb上には、既にたくさんの情報があります。Laravel特有の現象としてではなく、サーバー設定の問題として検索してください。

この方法は比較的面倒で、経験も必要です。ある程度、知識がある方におすすめします。(知識がある方は、この記事は不要でしょうけれど。)

開発機限定の簡単な方法

開発機が完全に外部から閉じている環境であれば、Webサーバーの動作ユーザーとグループを自分のものに変更するのが一番簡単な方法です。Webサーバーの設定ファイルには、どのユーザー/グループで実行するのかを指定できるようになっています。それを自分のユーザー/グループに変更します。

但し、セキュリティーを緩くしてしまうので、外部からのアクセスをしっかり遮断するため、ファイヤーウォール等でアクセスポートを確実に閉じていることを確認しましょう。もし、Webサーバー以外であっても、自分のサーバーから外へ開いているポートがあるなら、避けるのが賢明かもしれません。(コンピューター本体だけでなく、ルーターなどの設定の知識をしっかりとお持ちなら、その限りではありません。)

つまり、完全に個人で開発しており、自分のデスクトップを開発専用に使用し、外部からのアクセスを受け付けないような状況であれば、お手軽にこの方法を取ることが可能です。

調べる量も最小限度で済みます。Webサーバーの設定ファイルがどこにあるのか調べ(検索すれば、簡単にみつかるでしょう)、そのファイルの指定箇所を変更します。

Linux上のApacheであれば、多くの場合、設定ファイルは/etc/apache2上のhttpd.confであることが多いです。設定内容が別ファイルに指定されていることもあります。例えば、私の使用しているopenSUSE13.1では、同じディレクトリーのuid.confファイルで指定されています。

Nginxの場合は調べていませんが、Nginx自身の設定ファイル中のユーザー/グループを変更するか、もしくはPHPがfast-cgiで動作していますので、そちらの設定を変更するかでしょう。

いずれにせよ、この方法が使用できるのであれば、設定ファイルを変更するだけですので、一番手間は少なくて済みます。

ただし、apache2やphp5の主にセッション情報が既に保存ファイルに書き込まれていると、前の起動オーナーの所有になっており、そのためパーミッションが使えません。設定ファイルを調べ、セッションの書き込み先ディレクトリーの所有者を自分のユーザー名に変更する必要があります。(一番簡単なのは、OSをインストールした際に、Webサーバーなどをインストールしたら、アクセスする前に書き換えてしまうことです。)

ファイル監視

普段からファイル監視の手段を使用している方なら、app/storage下のファイルを監視し、ファイルの状態変化時に両方の環境からアクセス可能になるように、設定することができます。

多分、ルートユーザーの権限で監視し、所有者/所有グループ、パーミッションの変更を行う必要があるでしょう。

どのようにすれば、Webサーバーと自分(もしくは開発グループ)のアカウントの両方からアクセスできるかは、次のセクションの1〜4を参考にしてください。

通常の方法

Webサーバーにアクセスがあった場合、実行ユーザーにサーバー設定ファイルで指定されたものを使用するう場合、サーバー設定の観点から見れば、一般的なやり方です。

先ず、自分のアカウントにWebサーバーの動作グループを追加します。次に、ドキュメントルートかapp/storage下のディレクトリー/ファイルをWebサーバーの動作グループの所有にし、グループに対する読み書きを許可します。

説明中はWebサーバーの動作グループをwww-groupにしています。皆さんの環境に合わせてください。(但し、この方法はサザエパターン『サザエさんで何度も繰り返される、同じシナリオのこと』の一つ、料理番組の「この続きは、また明日」となっています。;P つまり、最後のステップを上手く行う方法が見つからないため、完全自動化できません。)

1. 自分のアカウントをサーバーの動作グループに追加

追加の方法はいろいろありますが、以下のコマンドが安全です。

sudo gpasswd -a 自分のユーザー名 www-group

これで、Webの動作グループに、自分のアカウントを追加できました。ここで一旦ログアウトし、再度ログインしてください。確認してみましょう。

id

2. ディレクトリーのグループ変更

ディレクトリー下のファイルとディレクトリーを再帰的に、全部Webサーバーの動作グループに変更します。今回は作業ディレクトリーはプロジェクトのルートで、app/storage下のみ変更することにしましょう。

sudo chgrp -R www-group app/storage

3. 既存ディレクトリーのパーミッション変更

ディレクトリーのパーミッションを775、つまりユーザーと同一グループに対しては読み書き実行を許可、その他については読み込みと実行を許可します。2の部分はセットグループIDの指定です。ディレクトリー下に作成されるファイルの所有グループが、実行者のものではなく、ディレクトリーのグループと同じになります。

sudo chmod 2775 app/storage
find app/storage -type d -exec sudo chmod 2775 {} +

4. 既存ファイルのパーミッション変更

既存ファイルにユーザーとグループの読み書き、その他は読み込みだけのパーミッションを設定します。

find app/storage -type f -exec sudo chmod 0664 {} +

新しくファイルが作成されることがなければ、この時点でおしまいです。これで、既に存在するapp/storage下のディレクトリーとファイルに関しては問題が無くなりました。

しかし、Laravelでは必ずapp/storage下にファイルが書き込まれるため、新規に作成されるファイルのパーミッションに対する設定が必要となります。ただし、セキュリティーを優先させる場合は、以降の2ステップを行うよりも、毎回find app/storage -type f -exec sudo chmod 0664 {}を行うことをおすすめします。

5. 自分のumaskの変更

新規作成時のファイルのパーミッションは、通常デフォルトで755になります。つまり、グループに対する書き込みは許可されていません。これは新規作成時のパーミションを決めるumaskが0022に設定されていることが多いからです。セキュリティー的な問題がなければ、自分が作成する新規ファイルは、同一グループからの書き込みを許すように変更することが可能です。

これを行わない場合、app/storage下に直接であれ、間接であれ、新しくファイルを作成する場合パーミッションは今までどおり644になりますので、グループに対する書き込み許可を与える必要はそのままです。

昔のUnixでは、グループに対する書き込みは通常許可されるようになっていたのですが、セキュリティーリスクになったため、今ではデフォルトでは許可しないのが普通になりました。つまり、他のグループからの書き込みを許してしまうのは、セキュリティーが甘くなることを指します。

umaskを自動で変更するには、通常シェルの設定ファイルで行います。Bashを使用している場合、自分のホームディレクトリー下に存在する.bashrcか.bash_profileで指定しましょう。端末を起動している間だけ、変更したい場合は、直接コマンドを叩くこともできます。

umask 0113

これで自分で作成した新規ファイルに全部、グループの書き込み許可が自動的に付きます。

ただし、これにより、以降作成されるファイルは全部664になり、他のグループから書き込み可能になります。

6. Webサーバーのumaskの変更

Ubuntuに関しては、umaskを設定する方法が存在するようです。私の使用しているopenSUSEのApacheでは存在しないようです。Apache2の起動シェルを読んでみましたが、動作環境を設定するような特別なファイルは存在していないようです。どうしてもというなら、起動シェルを変更して無理にumaskを設定することも可能でしょう。

ただし、開発機でそこまで行うのは多分やりすぎです。つまり、新規ファイルに同一グループによる書き込みを許してしまうのは、セキュリティーを低下させてしまいます。それが、許される環境であれば、Webサーバーの動作環境を自分のユーザー/グループに変更するほうが簡単です。もしくは、app/storage下のファイルを監視し、変更があればパーミッションを変更する方法が、一番手間がかかりません。

逆にセキュリティーも維持し、更に各ユーザーの利便性も最高にしたいのであれば、一番最初のファイル所有者/グループとしてアクセスを実行する方法を取りましょう。共有サーバーやPaaSなどでは、こうした設定は一般的ですので、情報もたくさんあります。

注意点

開発環境と実行時環境で、Webサーバーの実行状態やパーミッションの状況が異なる可能性に注意を払ってください。更に転送や圧縮に使用するツールの設定などでもファイルのパーミッションは影響を受けます。

つまり、転送するだけで上手く行くこともあれば、上記のような設定をデプロイ時に、再度行う必要がある場合もあるということです。storage下のディレクトリーは必要でしょうが、それらのサブディレクトリー下のファイルは、本番環境へ移動しないことのほうが多いはずです。