2015年7月6日月曜日

vagrantとapacheと権限

vagrantでCakePHPの環境を作ろうと思って色々ハマったのでメモ。

ちなみにゲストOSはCentOS7。

やろうとしたこと

  • ローカルの(vagrant upしたディレクトリの)app/配下を共有フォルダとしてマウント
  • appにCakePHPをインストール
  • 共有フォルダとしてマウントした/app/webrootをapacheのドキュメントルートにする
  • /app配下はapacheユーザで書き込みできるようにする
  • vagrantのprovisioningでphp、apache、CakePHPのインストールと設定を行う

ハマりポイント1

最初、apacheで書き込みができるようにということで、synced_folderのオプションでgroupをapacheにし、グループ向けのパーミッションを指定してみた。

config.vm.synced_folder "./app", "/app", create: true,
                owner: "vagrant", group: "apache",
                mount_options: %w(dmode=775 fmode=764)

apacheがインストールされている場合、この設定自体は問題なく機能する。
が、インストールされていない場合はvagrant upの時点でエラーになる。

どういうことかというと、synced_folderのマウントはOS起動後、provisioningの前に行われるのだが、provisioningが行われていないということはapacheがインストールされておらず、apacheというグループも存在しないためマウントに失敗する。

  1. OS起動
  2. synced_folderのマウント ←ここでapacheグループが存在せずエラー
  3. provisioning ←ここまでこない

解決策

マウント時のユーザとグループは変更せずに、apacheをvagrantグループに追加することにした。

config.vm.synced_folder "./app", "/app", create: true,
                mount_options: %w(dmode=775 fmode=764)
sudo yum -y install httpd
sudo usermod -aG vagrant apache

apacheがvagrantグループに入るのはどうよ、とも思うけど、開発環境だしまぁいいかなと割り切った。

他にもsynced_folderを設定せずに、apache起動時にゲストOS側で動的にマウントさせるようにするという案もあったが、共有フォルダの設定がVagrantfileから分かれてしまうのが嫌なのと、起動時に小細工が必要なのが面倒だったので採用しなかった。

ハマりポイント2

マウントした/appをドキュメントルートにするために、/etc/httpd/conf/httpd.conf内の/var/www/htmlになっている箇所を全部/app/webrootに置換した。

そしたら/app/webroot must be a directoryみたいなエラーが出てapacheが起動しなくなった。
この時点ではまだCakePHPをインストールしていなかったため、/app/webrootが存在していなかった。存在していないディレクトリはDocumentRootに出来ないようだ。

解決策1

apacheの設定よりも先にCakePHPをインストールして/app/webrootが存在するようにしておく。
あるいはとりあえずmkdir /app/webrootとかしておく。

解決策2

VirtualHostの設定ではDocumentRootが存在していなくても大丈夫らしいのでそちらで設定する。

<VirtualHost *:80>
    DocumentRoot /app/webroot
    EnableSendfile off

    <Directory "/app/webroot">
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

ハマりポイント3

app/配下で編集した.cssや画像が更新されない。

これはvagarnt EnableSendfileとかで検索してもらうと事情がわかると思うが、ネットワークマウントしたDocumentRootではカーネルのsendfileを使用したファイル配信はうまくいかないことがあるということらしい。

解決策

この機能はオフにする。

EnableSendfile Off

参考:EnableSendfile ディレクティブ