LoginSignup
5
2

More than 5 years have passed since last update.

Capistrano3でSymfony2をデプロイしたら、app/cache配下に書き込みできなくて数時間ハマった

Last updated at Posted at 2017-05-26

はじめに

[UNMAINTAINED] になった Capistrano2 + Capifonyプラグインから、Capistrano3 + capistrano/symfonyプラグインに切り替えたら、キャッシュ周りで数時間ハマりました。

何が起きたか

Capistrano3 + capistrano/symfonyプラグインに切り替えて、デプロイしたところ、直後のアクセスでApacheが下記のようなエラーを吐きました。

request.CRITICAL: Exception thrown when handling an exception (InvalidArgumentException: The directory "{/path/to/app}/releases/{timestamp}/app/cache/prod/jms_serializer" is not writable. at {/path/to/app}/releases/{timestamp}/vendor/jms/metadata/src/Metadata/Cache/FileCache.php line 17) {"exception":"[object] (InvalidArgumentException(code: 0): The directory \"{/path/to/app}/releases/{timestamp}/app/cache/prod/jms_serializer\" is not writable. at {/path/to/app}/releases/{timestamp}/vendor/jms/metadata/src/Metadata/Cache/FileCache.php:17)"} []

前置きしておきますが、jms_serializerは無関係です。
他のライブラリも同様に、app/cacheに書き込みできなくて、エラーを吐きます。

app/cache0777 に設定しているはず

config/deploy.rbには、下記のように、app/cache0777にしているつもりでした。

# config/deploy.rb

# Set correct permissions between releases, this is turned off by default
set :file_permissions_paths, ["app/cache"]
set :file_permissions_users, ["apache"]
set :file_permissions_chmod_mode, "0777"
set :permission_method, :acl
after "deploy:updated", "deploy:set_permissions:acl"

Symfony的には、ACLを使うべし

ファイルのパーミッションについて、Symfonyの公式ドキュメントに詳しい説明があります。

$ HTTPDUSER=$(ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1)
# # if this doesn't work, try adding `-n` option
$ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX var
$ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX var

setfaclコマンドによって、Webサーバの実行ユーザー(apache, www-dataなど)とパーミッションを設定するユーザー($(whoami))双方にフルアクセスを与えるコマンド例が記載されています。

setfacl は実行されている

Capistrano::FilePermissionsREADMEを見ると、下記のようにコマンドを実行していることが説明されています。

[..] setfacl -Rn -m u:www-data:rwX -m u:<deploy-user>:rwX <path-to-app>/shared/app/logs <path-to-app>/<release>/app/cache

実際、デプロイ時のコンソールログを見ると、下記のようにsetfaclコマンドが実行されています。

00:06 deploy:set_permissions:acl
      01 setfacl -Rn -m u:{web server user}:rwX -m u:{deploy user}:rwX {/path/to/app}/releases/{timestamp}/app/cache
    ✔ 01 {deploy user}@{web server} 0.047s
      02 setfacl -dRn -m u:{web server user}:rwX -m u:{deploy user}:rwX {/path/to/app}/releases/{timestamp}/app/cache
    ✔ 02 {deploy user}@{web server} 0.047s

しかし、パーミッションは0777になっていない

確認してみると、パーミッションは0777になっていないことに気付きます。

[{deploy user}@{web server} {/path/to/user}]$ ls -la current/app/cache

drwxr-xr-x+ 3 {deploy user} {group} 4096  5 25 19:42 2017 .
drwxr-xr-x  5 {deploy user} {group} 4096  5 25 19:42 2017 ..
drwxr-xr-x+ 9 {deploy user} {group} 4096  5 25 19:42 2017 prod
[{deploy user}@{web server} {/path/to/user}]$ getfacl current/app/cache/*
# file: current/app/cache/prod
# owner: {deploy user}
# group: {group}
user::rwx
group::r-x
other::r-x

既知の問題ではある

おかしいですね。だけど、これはみんな踏んでいる地雷なのでは?ということで、Githubを見ていると、下記のPRを発見しました。

remove_n_option.png

詳しいことは理解しきってはいないですが、どうやら、setfaclnオプションが不要だったみたいです。
あれ、これ、Mergedになっているけれども...

修正はされているけれど、リリースされていない

そう、このPRがマージされたのは、2016-6-29で、最新のcapistrano-file-permissions 1.0.0は、2016-1-15のままなんですよね。
これに気付くのに、もう小一時間かかりました。

で、早くリリースしてくれっていうissueが2017-5-3にすでに切られてました。

umask を使うことに

ACLによるファイルパーミッションをあきらめるとなると、umaskを使う方法がSymfonyの公式で紹介されています。

If none of the previous methods work for you, change the umask so that the cache and log directories are group-writable or world-writable (depending if the web server user and the command line user are in the same group or not). 
To achieve this, put the following line at the beginning of the bin/console, web/app.php and web/app_dev.php files:

bin/console(symfony2はapp/console)、web/app.phpweb/app_dev.phpのエントリポイントとなるファイルの先頭で、umask(0000);としておくと、ファイルパーミッションが0777になるよと説明されています。

実際、app/consoleにも下記のコメントが既に埋まっていたりします。

// app/console

// if you don't want to setup permissions the proper way, just uncomment the following PHP line
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
umask(0000); // 今回ここのコメントを解除しました

おわりに

まとめると、下記2つの対応をすることでapp/cacheに書き込めない問題を回避しました。

  • Capistranodeploy:set_permissions:aclは削除(何もしないようにする)
  • app/consoleweb/app.phpweb/app_dev.phpの先頭にumask(0000);を追加

世界中のSymfonyユーザーのために、capistrano-file-permissionsの新バージョンがリリースされることを希望します。
(みんな、umask使っているのかな。ひょっとして常識?)

ではでは。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2