カテゴリー
Laravel

LaravelのCacheのPermissionについて (failed to open stream: Permission denied)

artisanを操作するユーザーとWebサーバーの実行ユーザーが違うのは多々あるはずやねん。

artisanを使うときはahraユーザー、webはapacheとかね。ほんでね、お互いグループは共有してるとするやで。つまり、グループでのパーミッション指定があってればええっちゅうこっちゃね。

せやけども、キャッシュ機構(ファイルにストアするやつね)を使ってる箇所があるとするやろ?

そうすると、storage/framework/cache なディレクトに作られるファイルのパーミッションが、artisanのときは、ahra:ahra になるし、webのときは apache:apache になるわけよ。

せやけども、問題はこのファイルのパーミッションが644になってる場合があるわけよね。

ほんで、ahraユーザーで、artisan clear:cache するとさ、

Application cache cleared!

って出るんやけども、実際ね、クリアできてへん。

ほんで、実際にキャッシュ操作するコマンド作って動かしたらさ、webで作られてるとこけるわけやねん。

failed to open stream: Permission denied

やね。

まあ、つまり、キャッシュをファイルに書き出す時のパーミッションをね、グループも書き込み可能にしたいわけやねん。

調べるとさ、カスタムのファイルストアマネージャ作ったとか、ファイルマスク変更するとか、いろいろあったわけやねんけどね、今のLaravel(7.x)ならもっとこう、なんかあるんやないかなって。

あった。Illuminate/Cache/FileStore.phpやね。

    /**
     * Create an instance of the file cache driver.
     *
     * @param  array  $config
     * @return \Illuminate\Cache\Repository
     */
    protected function createFileDriver(array $config)
    {
        return $this->repository(new FileStore($this->app['files'], $config['path'], $config['permission'] ?? null));
    }

出たわね。

パーミッション指定できるやん。というわけで、config/cache.phpのココを

        'file' => [
            'driver' => 'file',
            'path' => storage_path('framework/cache/data'),
            'permission' => 0664,
        ],

こうかな。

これでwebの方で作られたキャッシュファイルを見てみると、確かに、グループが書き込み可能になっとった。これでキャッシュの更新自体は成功や…!たしかに、ahraユーザーでキャッシュ更新する処理は成功するようになったンゴ。

だがしかし、artisan clear:cache の削除はやっぱり効かへん…。

    /**
     * Create the file cache directory if necessary.
     *
     * @param  string  $path
     * @return void
     */
    protected function ensureCacheDirectoryExists($path)
    {
        if (! $this->files->exists(dirname($path))) {
            $this->files->makeDirectory(dirname($path), 0777, true, true);
        }
    }

ふーむ、おかしいな。ディレクトリのパーミッションは指定してるんやが…。

調べるンゴねぇ。

内部的に、mkdir() で、指定のpermissionを渡しているんだが、それでもそうならないのは、mkdir()はumaskによる制限がかかるんやて。

なるほど。

umask()を、ahraユーザーとwebでそれぞれ実行してみた結果。

ahraは0002、webやと0022や。

そら(0777のディレクトリをmkdir()で作ることは)そう(できない)よ。

これは教育やろなぁ。

というわけであとはumaskの設定をってことになるんやが、手取り早いのは、laravelのAppServiceProvider.phpあたりで

    public function register()
    {
        // overwrite umask
        umask(0002);

かな。悪手な気がするけれども。サーバー設定いじれないときはこうするしかない。

これで、ahraユーザー、webのどちらで作られたキャッシュファイルでも同じように操作できるようになったで。

ええんちゃうか、最高ちゃう。

ついでやけども、ログ(config/loggin.php)も同様やね。

        'single' => [
            'driver' => 'single',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'permission' => 0664,
        ],

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'days' => 14,
            'permission' => 0664,
        ],

single と daily で作られるファイルのパーミッションが指定可能や。

アプリケーションが稼働し続けることによって自動で作成されたファイルでややこしいことにならないように、最初にはっきりしておきたいところやね。

追記(2020.11.16)

あかん。あかんで。結局オーナーとグループが違うわけやから、動かん。コマンドが先に実行しちゃった場合は、グループがapacheにならへん。

そこで、SGIDよ。

ディレクトリに設定すれば、そのディレクトリ配下に作成されるやつのグループがそいつと同じものになるっちゅうやつやね。

つまり、Laravelなら、storageとbootstrap/cacheに設定しておけばええと思うで。

例えば、storageディレトリのグループがapacheなら。

chmod g+s storage

で。

そしたら、その中に作られるファイルやディレクトリは基本的にapacheになるっちゅうことやね。

セキュリティ的にあれやけども。しゃーない、切り替えていけ。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です