menu

Questions & Answers

How to setup laravel file permission once and for all

I have followed this upvoted answer and did the following:

sudo chown -R my-user:www-data /var/www/domain.com/
sudo find /var/www/domain.com/ -type f -exec chmod 664 {} \;
sudo find /var/www/domain.com/ -type d -exec chmod 775 {} \;
sudo chgrp -R www-data /var/www/domain.com/storage /var/www/domain.com/bootstrap/cache
sudo chmod -R ug+rwx /var/www/domain.com/storage /var/www/domain.com/bootstrap/cache

Everything works fine, but whenever a directory (within the storage directory) is created by my-user and not www-data user, the webserver can't write to it or vice versa. Unless I rerun those commands after the directory has been created.

Notes: sometimes I run commands with my-user that create directories, and sometimes the www-data user create directories. (within the storage directory).

Also, my-user is already within the www-data group.

How can I avoid permission errors? without running all those commands again.

Comments:
2023-01-19 23:30:12
Why not create an artisan command. As soon as you run the artisan command it creates a folder on storage with name you supplied. And then also run the above script on same artisan command.
2023-01-19 23:30:12
There is already an answer to this question, please check stackoverflow.com/questions/30639174/…
2023-01-19 23:30:12
@AnkitJindal did you read my question (fully)? I haven't found a solution there. If you think a certain answer there could solve this, maybe link to it directly
Answers(7) :

You mentioned that your user belongs to the same group as the www-data user so the following from this answer might work (I tried it in ubuntu but similar steps might work in your *nix OS):

Type sudo gedit ~/.bashrc

Find and change any umask line to umask 002 this means that for you and your group all permissions can be set for new files and directories. In practice this means new files are created with 664 permissions and new directories with 775

This should cover new files created with your user account. Of course you need to be careful whenever you do sudo create this file because this will create it for the root user.

Note this is not a perfect solution as there are still things only the file owner and root user can do (changing owners or permissions for example) but it will probably cover most other cases

From the laravel documentation, https://laravel.com/docs/8.x/filesystem#local-files-and-visibility , you can set permissions of a filesystem in the config/filesystems.php file:

'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
    'permissions' => [
        'file' => [
            'public' => 0644,
            'private' => 0600,
        ],
        'dir' => [
            'public' => 0755,
            'private' => 0700,
        ],
    ],
],

Also from the docs:

Files may either be declared public or private. When a file is declared public, you are indicating that the file should generally be accessible to others. For example, when using the S3 driver, you may retrieve URLs for public files.

Option 1 add www-data group to my-user:

sudo adduser www-data my-user

Option 2 change user of php-fpm into my-user (ref):

find options user and group in www.conf, and change it into [my-user] group=mygroup

Comments:
2023-01-19 23:30:12
I have already tried adding my user to the www-data group, still the same. Your option two doesn't seem like a safe solution.
2023-01-19 23:30:12
If your server only have 1 virtual host it's 100% safe, if not just do it on one virtual host
2023-01-19 23:30:12
Option 2 is the way to go, having 0 errors with it.

My best solution would be to create an artisan command.

This way you dont use linux way of creating folder and setting up permissions every time.

So create an artisan command that executes as below

php artisan createStorageFolder:FolderName

This will automatically set user permission to apache:apache or similar. If not you can also execute linux/shell command to set the permission on artisan method.

Comments:
2023-01-19 23:30:12
How will this "automatically set user permission to apache:apache or similar"? I can't see how this answers my question.
2023-01-19 23:30:12
you can run shell command inside a method. So as soon as you create a folder inside the storage folder, you can set the permission using shell script in artisan command.

Give this a try:

# give the newly created files/directories the group of the parent directory 
# e.g. the laravel group

sudo find $project_Path/bootstrap/cache -type d -exec chmod g+s {} \;
sudo find $project_Path/storage -type d -exec chmod g+s {} \;

# let newly created files/directories inherit the default owner 
# permissions up to maximum permission of rwx e.g. new files get 664, 
# folders get 775

sudo setfacl -R -d -m g::rwx ./storage
sudo setfacl -R -d -m g::rwx ./bootstrap/cache
Comments:
2023-01-19 23:30:12
I run last two commands and application throws 500 server error.
2023-01-19 23:30:12
can you give me the details of 500 server error , give me the detailed exception please.
2023-01-19 23:30:12
No sorry I can not replicate the error. May be it was a fault on my site. I really don't know.

Had this issue with a jr web dev's webroot area (we blocked him off from general webroot access where projects were). Simple fix was just to add a cronjob that changed the permissions every minute.

Comments:
2023-01-19 23:30:12
Once the directory has been created, it should be immediately accessible to both my-user and www-data user. If not, errors will occur, so a delayed CronJob won't fix this. Also, as stated in the question, I am not looking to rerun commands.
2023-01-19 23:30:12
I don't think this is a long term approach

how 'bout sudo chown -R $USER:$USER * on your root of laravel project folder?
or
sudo chown -R $USER:$USER [laravel folder name] if you're outside/ in parent directory of you're laravel folder / project ?

Comments:
2023-01-19 23:30:12
/!\ The first command above could seriously mess-up your system permissions if you mistakenly run it in the wrong folder. Try to write your commands so that you never have to use the wildcard symbol alone, especially if you're going to execute that command with sudo.
2023-01-19 23:30:12
How about using "." ?
2023-01-19 23:30:12
understandable,,,
2023-01-19 23:30:12
"." is not safe either because if you ever run this command in the wrong directory by mistake you could mess-up the whole system. Someone copy pasting your command above without thinking could make that mistake. The safest is to provide the full path sudo chown -R $USER:$USER /srv/www/myproject/ that way if you ever run this command in the wrong directory (for example you press the up arrow in your terminal and execute the command where you shouldn't) the command will only ever apply to to that specific folder. Not trying to lecture you, just sharing a useful tip :-)