Laravel daily log created with wrong permissions

Solution 1:

Laravel version 5.6.10 and later has support for a permission element in the configuration (config/logging.php) for the single and the daily driver:

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

No need to juggle with Monolog in the bootstrap script.

Specifically, support was added in https://github.com/laravel/framework/commit/4d31633dca9594c9121afbbaa0190210de28fed8.

Solution 2:

IMPORTANT This answer is incompatible with laravel 5.5+. Please see this answer: Custom (dynamic) log file names with laravel5.6

Let's start with what is constant.

You have a php artisan command, run by root.

It is safe to assume that this command is executed daily.

Solution No 1:

Given that the user that creates the files is the one that has the permission to write to it by default, we can separate the logs by user as such:

App/start/global.php

/*
|--------------------------------------------------------------------------
| Application Error Logger
|--------------------------------------------------------------------------
|
| Here we will configure the error logger setup for the application which
| is built on top of the wonderful Monolog library. By default we will
| build a basic log file setup which creates a single file for logs.
|
*/

Log::useDailyFiles(storage_path().'/logs/laravel-'.posix_getpwuid(posix_geteuid())['name'].'.log');

If your www-data user were to create an error log, it would result in: storage/logs/laravel-www-data-2015-4-27.log.

If your root user were to create an error log, it would result in: storage/logs/laravel-root-2015-4-27.log.

Solution No 2:

Change the log used by your artisan command, in your php script.

In your run() function, add this line at the start:

Log::useFiles(storage_path().'/logs/laravel-'.__CLASS__.'-'.Carbon::now()->format('Y-m-d').'.log');

If your class's name is ArtisanRunner, then your log file will be:

storage/logs/laravel-ArtisanRunner-2015-4-27.log.

Conclusion: Solution number 1 is better, given that it delineates your logs by user, and hence no errors will occur.

EDIT: As pointed out by jason, get_current_user() returns the script's owner name. Hence, for solution no.1 to apply, chown your artisan class files to the required username.

Solution 3:

For Laravel 5.1 I use the following towards the bottom of bootstrap/app.php (as mentioned in the docs):

/**
 * Configure Monolog.
 */
$app->configureMonologUsing(function(Monolog\Logger $monolog) {
    $filename = storage_path('logs/laravel-'.php_sapi_name().'.log');
    $handler = new Monolog\Handler\RotatingFileHandler($filename);
    $monolog->pushHandler($handler);
});

There are lots of other Handlers that you can use instead, of course.

Solution 4:

For such purposes you should use advanced ACL on your files and directories. setfacl would be your answer here. If you want to give www-data user permissions to write on root's files in specific directory, you can do it like this:

setfacl -d -m default:www-data:you-chosen-group:rwx /my/folder

After issuing this you're setting permissions to rwx for www-data user on all files in /my/folder/ no matter who created those. Please, see this and this question for reference. Also, you can check docs for setfacl.

Let me know if this helps.