How to set up file permissions for Laravel?

前端 未结 15 2136
忘了有多久
忘了有多久 2020-11-22 00:08

I\'m using Apache Web Server that has the owner set to _www:_www. I never know what is the best practice with file permissions, for example when I create new La

15条回答
  •  一生所求
    2020-11-22 00:39

    The solution posted by bgles is spot on for me in terms of correctly setting permissions initially (I use the second method), but it still has potential issues for Laravel.

    By default, Apache will create files with 644 permissions. So that's pretty much anything in storage/. So, if you delete the contents of storage/framework/views, then access a page through Apache you will find the cached view has been created like:

    -rw-r--r-- 1 www-data www-data 1005 Dec  6 09:40 969370d7664df9c5206b90cd7c2c79c2
    

    If you run "artisan serve" and access a different page, you will get different permissions because CLI PHP behaves differently from Apache:

    -rw-rw-r-- 1 user     www-data 16191 Dec  6 09:48 2a1683fac0674d6f8b0b54cbc8579f8e
    

    In itself this is no big deal as you will not be doing any of this in production. But if Apache creates a file that subsequently needs to be written by the user, it will fail. And this can apply to cache files, cached views and logs when deploying using a logged-in user and artisan. A facile example being "artisan cache:clear" which will fail to delete any cache files that are www-data:www-data 644.

    This can be partially mitigated by running artisan commands as www-data, so you'll be doing/scripting everything like:

    sudo -u www-data php artisan cache:clear
    

    Or you'll avoid the tediousness of this and add this to your .bash_aliases:

    alias art='sudo -u www-data php artisan'
    

    This is good enough and is not affecting security in any way. But on development machines, running testing and sanitation scripts makes this unwieldy, unless you want to set up aliases to use 'sudo -u www-data' to run phpunit and everything else you check your builds with that might cause files to be created.

    The solution is to follow the second part of bgles advice, and add the following to /etc/apache2/envvars, and restart (not reload) Apache:

    umask 002
    

    This will force Apache to create files as 664 by default. In itself, this can present a security risk. However, on the Laravel environments mostly being discussed here (Homestead, Vagrant, Ubuntu) the web server runs as user www-data under group www-data. So if you do not arbitrarily allow users to join www-data group, there should be no additional risk. If someone manages to break out of the webserver, they have www-data access level anyway so nothing is lost (though that's not the best attitude to have relating to security admittedly). So on production it's relatively safe, and on a single-user development machine, it's just not an issue.

    Ultimately as your user is in www-data group, and all directories containing these files are g+s (the file is always created under the group of the parent directory), anything created by the user or by www-data will be r/w for the other.

    And that's the aim here.

    edit

    On investigating the above approach to setting permissions further, it still looks good enough, but a few tweaks can help:

    By default, directories are 775 and files are 664 and all files have the owner and group of the user who just installed the framework. So assume we start from that point.

    cd /var/www/projectroot
    sudo chmod 750 ./
    sudo chgrp www-data ./
    

    First thing we do is block access to everyone else, and make the group to be www-data. Only the owner and members of www-data can access the directory.

    sudo chmod 2775 bootstrap/cache
    sudo chgrp -R www-data bootstrap/cache
    

    To allow the webserver to create services.json and compiled.php, as suggested by the official Laravel installation guide. Setting the group sticky bit means these will be owned by the creator with a group of www-data.

    find storage -type d -exec sudo chmod 2775 {} \;
    find storage -type f -exec sudo chmod 664 {} \;
    sudo chgrp -R www-data storage
    

    We do the same thing with the storage folder to allow creation of cache, log, session and view files. We use find to explicitly set the directory permissions differently for directories and files. We didn't need to do this in bootstrap/cache as there aren't (normally) any sub-directories in there.

    You may need to reapply any executable flags, and delete vendor/* and reinstall composer dependencies to recreate links for phpunit et al, eg:

    chmod +x .git/hooks/*
    rm vendor/*
    composer install -o
    

    That's it. Except for the umask for Apache explained above, this is all that's required without making the whole projectroot writeable by www-data, which is what happens with other solutions. So it's marginally safer this way in that an intruder running as www-data has more limited write access.

    end edit

    Changes for Systemd

    This applies to the use of php-fpm, but maybe others too.

    The standard systemd service needs to be overridden, the umask set in the override.conf file, and the service restarted:

    sudo systemctl edit php7.0-fpm.service
    Use:
        [Service]
        UMask=0002
    Then:
    sudo systemctl daemon-reload
    sudo systemctl restart php7.0-fpm.service
    

提交回复
热议问题