413

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 Laravel 5 project.

Laravel 5 requires /storage folder to be writable. I found plenty of different approaches to make it work and I usually end with making it 777 chmod recursively. I know it's not the best idea though.

The official doc says:

Laravel may require some permissions to be configured: folders within storage and vendor require write access by the web server.

Does it mean that the web server needs access to the storage and vendor folders themselves too or just their current contents?

I assume that what is much better, is changing the owner instead of permissions. I changed all Laravel's files permissions recursively to _www:_www and that made the site work correctly, as if I changed chmod to 777. The problem is that now my text editor asks me for password each time I want to save any file and the same happens if I try to change anything in Finder, like for example copy a file.

What is the correct approach to solve these problems?

  1. Change chmod
  2. Change the owner of the files to match those of the web server and perhaps set the text editor (and Finder?) to skip asking for password, or make them use sudo
  3. Change the owner of the web server to match the os user (I don't know the consequences)
  4. Something else
Script47
  • 14,230
  • 4
  • 45
  • 66
Robo Robok
  • 21,132
  • 17
  • 68
  • 126
  • 10
    I think `777` is too much freedom, because it includes all permissions for everyone. – Robo Robok Jun 04 '15 at 14:10
  • 1
    From the Laravel docs: Directories within the `storage` and the `bootstrap/cache` directories should be writable by your web server –  Sep 25 '16 at 14:04
  • 1
    use fcgi and you can 755/644 for all (incl. public/storage) – Jeffz Mar 24 '18 at 02:11
  • @jww agree could we move the question to serverfault instead of putting it on hold? – wp78de Dec 24 '18 at 07:27

22 Answers22

1028

Just to state the obvious for anyone viewing this discussion.... if you give any of your folders 777 permissions, you are allowing ANYONE to read, write and execute any file in that directory.... what this means is you have given ANYONE (any hacker or malicious person in the entire world) permission to upload ANY file, virus or any other file, and THEN execute that file...

IF YOU ARE SETTING YOUR FOLDER PERMISSIONS TO 777 YOU HAVE OPENED YOUR SERVER TO ANYONE THAT CAN FIND THAT DIRECTORY. Clear enough??? :)

There are basically two ways to setup your ownership and permissions. Either you give yourself ownership or you make the webserver the owner of all files.

Webserver as owner (the way most people do it, and the Laravel doc's way):

assuming www-data (it could be something else) is your webserver user.

sudo chown -R www-data:www-data /path/to/your/laravel/root/directory

if you do that, the webserver owns all the files, and is also the group, and you will have some problems uploading files or working with files via FTP, because your FTP client will be logged in as you, not your webserver, so add your user to the webserver user group:

sudo usermod -a -G www-data ubuntu

Of course, this assumes your webserver is running as www-data (the Homestead default), and your user is ubuntu (it's vagrant if you are using Homestead).

Then you set all your directories to 755 and your files to 644... SET file permissions

sudo find /path/to/your/laravel/root/directory -type f -exec chmod 644 {} \;    

SET directory permissions

sudo find /path/to/your/laravel/root/directory -type d -exec chmod 755 {} \;

Your user as owner

I prefer to own all the directories and files (it makes working with everything much easier), so, go to your laravel root directory:

cd /var/www/html/laravel >> assuming this is your current root directory
sudo chown -R $USER:www-data .

Then I give both myself and the webserver permissions:

sudo find . -type f -exec chmod 664 {} \;   
sudo find . -type d -exec chmod 775 {} \;

Then give the webserver the rights to read and write to storage and cache

Whichever way you set it up, then you need to give read and write permissions to the webserver for storage, cache and any other directories the webserver needs to upload or write too (depending on your situation), so run the commands from bashy above :

sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache

Now, you're secure and your website works, AND you can work with the files fairly easily

Andres Felipe
  • 4,292
  • 1
  • 24
  • 41
bgies
  • 11,986
  • 2
  • 18
  • 14
  • 9
    Great example, if there is no www-data user, use apache:apache in place of www-data (on some distros) – Denis Solakovic Oct 06 '16 at 09:42
  • 156
    I think people misunderstand too much the `anyone` concept. Linux's `anyone` flag means **any user**, not any person. You still need server access. – Marco Aurélio Deleu Oct 08 '16 at 12:23
  • @DenisSolakovic, I don't understand what www-data is? A user or group? I'm using Ubuntu and Xampp. What's www-data for me? – andreshg112 Jan 26 '17 at 00:28
  • 3
    @andreshg112 The first www-data is name of the user, and the second www-data is the name of the group. So it means the owner is apache and (this-group) apache. Use www-data:www-data or add your user to that group. (CLI: useradd -G {group-name} username ), and than you can chown to username:www-group – Denis Solakovic Jan 26 '17 at 10:24
  • @bgies: Thanks a lot for the good information. Question, you mentioned that you prefer your second example, is one more secured than the other, `755`, `644` vs`775`, `664`? Also, if you go with the second method, do you really need to run the commands suggested by bashy? Again, thanks a lot. – fs_tigre Apr 01 '17 at 15:45
  • 4
    @fs_tigre I don't think there is much difference at all for security... except I guess that there are two users to guess passwords for instead of one, and of course I log in all the time with my user account, so if I did it in an insecure way (normal FTP and using a password for instance) it could compromise the site, but I only login in with Putty and SSH, and when I use FTP it's SFTP, so no issues at all. The commands suggested by bashy are recommended because they set the sticky bit, so if your webserver creates subdirectories they will have the same owner/permissions as the parent – bgies Apr 05 '17 at 03:24
  • 4
    In the first method, wouldn't the user still not be able to upload files since you didn't give `write` permission the group? – Fahmi Jun 09 '17 at 03:33
  • 1
    Also I tried with the second method, but when I `touch` a new file, be it as normal user or as `www-data`, the new file doesn't seem to inherit the permission..? – Fahmi Jun 09 '17 at 04:18
  • 2
    is `sudo chgrp -R www-data storage bootstrap/cache` really useful after doing a `sudo chown -R my-user:www-data /path/to/your/root/directory`? – javier_domenech Jun 20 '17 at 08:28
  • @bgies What do you mean by `/path/to/your/root/directory`? Does it the `public` directory of Laravel app, which is set as the document root for the virtual host? or it is the Laravel's app root directory itself i.e. which everything is there? – SaidbakR Jul 04 '17 at 01:21
  • 2
    @SaidbakR Laravel's app root directory for the chown because most (all?) Laravel files are not in the public directory – bgies Jul 05 '17 at 06:06
  • I get this error `production.ERROR: UnexpectedValueException: The stream or file "/var/www/html/laravel/storage/job/248/import.log" could not be opened: failed to open stream: Permission denied in /var/www/html/laravel/bootstrap/cache/compiled.php` – NineCattoRules Oct 02 '17 at 11:18
  • I found the problem...it was my cronjob for atisan, I had to set my cronjob with root privileges like this `sudo -i` and then `crontab -e` – NineCattoRules Oct 02 '17 at 15:47
  • 3
    This answer should be in the official Laravel documentation, right after the introduction section. – nanocv Dec 16 '17 at 12:59
  • 1
    Thank for this. Just a request: could you add a note apart to mention in CentOS 7 user is not 'www-data', instead 'apache'. – Klaujesi Mar 04 '18 at 15:34
  • @bgies I am using Laravel 5.5.. trying to follow your instructions but some how Laravel is unable to execute Python but getting Permission Denied error. – Volatil3 Apr 11 '18 at 10:35
  • In "Your user as owner" section I think we can skip `sudo chgrp -R www-data storage bootstrap/cache` because it's already done. – llioor Jul 24 '18 at 16:31
  • 1
    @bgies Thank you for the answer +1! I have a question please. When a new log file is been created the file owner is www-data:www-data.. how can I set it automatically to :www-data as you mentioned in the "Your user as owner" section (As well the file permission)? – llioor Jul 24 '18 at 16:58
  • 2
    Do not run `sudo find /path/to/your/laravel/root/directory -type f -exec chmod 664 {} \;`! You will not be able to run any commands from the command line after this (e.g. everything in `vendor/bin/`)! I now have to work out how to get Laravel to work from the command line again. – CJ Dennis Aug 24 '18 at 02:14
  • I did the same thing for storage folder to make the laravel running `sudo find/path/to/your/laravel/root/directory/storage/ -type f -exec chmod 664 {} \;` `sudo find /path/to/your/laravel/root/directory/storage/ -type d -exec chmod 775 {} \;` – Fred Lai Oct 23 '18 at 21:35
  • 2
    @Fahmi It should be 664 as well, right? Currently, I cannot upload files thru FTP if permissions are set to 644. Is this a typo? – Valkyrurr Jan 13 '19 at 16:07
  • 2
    I created a bash shell script that does all the work based on your answer: https://github.com/marounmelhem/laravel-permissions-fix – Maroun Melhem May 09 '19 at 13:50
  • I have ownership on wwwrun:wwwrun (opensuse) and permissions as above (644/755). Composer / php now have no access to storage, but the site works. Change ownership to my user (no other changes) and it is reversed. Composer works, website does not... Any fix? – nepp95 Jul 09 '20 at 00:36
  • 1
    EVRY other WORD in CAPS does VERY little TO make YOUR point. – Mattt Aug 14 '20 at 20:11
  • @bgies Thanks for the great answer, but why the two commands at the end of your answer? You've said in comments that it's making the owner/permission sticky, but I can't see that, "rwx" doesn't have "t" in it... . Sorry I'm a noob but you've already given the user and the webserver the "7" in "755" and "6" in "644" so they can both read and write (as you've suggested in the last part of your answer), so probably no need to giving these permissions again...? – aderchox Sep 14 '20 at 02:14
  • I have a problem with that configuration when using artisan. storage and subfolders have 775, owner is my user and group is www-data. Now after Laravel itself created a storage/logs/laravel.log with www-data:www-data. The result is, that my user can't write to laravel.log anymore when doing php artisan ... Is there a solution for that? – alexandre Dec 02 '20 at 06:58
  • In addition to `sudo find . -type f -exec chmod 664 {} \;` and `sudo find . -type d -exec chmod 775 {} \;` I did `chmod 775 artisan` since that's an executable file (it starts with `#!/usr/bin/env php`) – Roel Koops Dec 21 '20 at 09:20
  • I used to have, "cannot read the log file in append mode" error for queued jobs. I have followed the answer and every thing worked fine for 5 days and not I am getting the same error. I could not figure out what went wrong. – Ravi Teja Jan 12 '21 at 14:40
  • This gives an error for me: `sudo find /path/to/your/laravel/root/directory -type f -exec chmod 644 {} \; ` `missing argument to `-exec'` I can't see how to fix it. – Vince Jan 29 '21 at 05:36
  • 1
    WARNING: If you have any executable scripts in this folder like `node_modules` or `vendor` with binaries doing `sudo find . -type f -exec chmod 664 {} \;` will break them by removing the exec permission. – Code Commander Feb 26 '21 at 22:27
  • Useful to me in working with Laravel in WSL2 – Fil May 02 '21 at 03:29
  • 1
    This work for me but only when I have set default permissions for the log files: https://stackoverflow.com/a/49379249/2834876 – Roman Grinev May 27 '21 at 16:32
  • 1
    Why 644 and not 600? – Inigo EC Jun 04 '21 at 13:31
  • 2
    I have it exactly as you wrote. BUT this solution does not cover new files created by www-data (like sessions, cache, ...). It generates the files with chmod 644 which means group can not delete the file. I have a problem in deploy script with it. Can not delete old files. – Čamo Jun 16 '21 at 17:21
  • what does the `{} \;` mean in `sudo find . -type f -exec chmod 664 {} \;` ?? – shamaseen Nov 25 '21 at 22:37
  • i still on 777 mode, because still denied , but every week the server have a virus, hm dunno why – Yogi Arif Widodo Apr 10 '22 at 05:36
  • @YogiArifWidodo that's why don't give 777, for security reasons you should at best set 775 and not more than that – Farhan Ibn Wahid Apr 10 '22 at 17:03
  • @FarhanIbnWahid but how about cache its will create a file , can other user on $user :www-data make a file ( the file cache ) ? dunno why still denied if i didnt set into 777 . – Yogi Arif Widodo Apr 11 '22 at 01:16
  • 1
    When using "My user as owner", I always get 500 server errors later for not be able to write to cache. – Bojmaliev May 25 '22 at 09:23
  • @shamaseen see askubuntu.com/a/339019/388489 for an explanation of what the `{} \;` does. – Kevin Wheeler Sep 01 '22 at 02:26
  • I am confused: if you set 755 permissions for folders, and you upload files with FTP with another user, you shouldn't be able to write on the folder. Am I missing something? – Giacomo M Jan 22 '23 at 16:52
  • @bgies in your second method where user is owner you've used `sudo find . -type d -exec chmod 775 {} \;` Is 775 correct or should it be 755? – adam78 Feb 03 '23 at 11:52
  • - adam78 775 is correct. The -type d is selecting directories, and they should be at 775 – bgies Feb 04 '23 at 13:24
  • @bgies. I note the laravel.log file gets generated inside the Storage/logs directory but with permissions set as 664 `-rw-rw-r--` or 644 `-rw-r--r--` isn't that a little insecure as everyone can read the file which could potentialy contain sensitive information? – adam78 Mar 12 '23 at 12:01
  • @bgies similarly running `sudo find . -type f -exec chmod 664 {} \;` means the .env file ends up as `-rw-rw-r--` meaning you've given everyone read access to it. Whilst I understand its not publicly accessible it still makes it vulnerable. – adam78 Mar 14 '23 at 14:10
85

The permissions for the storage and vendor folders should stay at 775, for obvious security reasons.

However, both your computer and your server Apache need to be able to write in these folders. Ex: when you run commands like php artisan, your computer needs to write in the logs file in storage.

All you need to do is to give ownership of the folders to Apache :

sudo chown -R www-data:www-data /path/to/your/project/vendor
sudo chown -R www-data:www-data /path/to/your/project/storage

Then you need to add your user (referenced by it's username) to the group to which the server Apache belongs. Like so :

sudo usermod -a -G www-data userName

NOTE: Most frequently, the group name is www-data but in your case, replace it with _www

BassMHL
  • 8,523
  • 9
  • 50
  • 67
  • 13
    +1 I like this approach. But I believe the `chown` commands should include the -R flag. Also, in laravel 5.1 and 5.2, instead of the vendor directory, you should give access to the bootstrap/cache directory. – Jason Wheeler May 24 '16 at 09:54
  • is there any way to test if this will work fine? I mean if the new log file is created in the storage/logs dir that would have correct permissions how I can check that? – StealthTrails Dec 26 '18 at 10:22
  • What you mean with `your computer needs to write in the logs file in storage`? File permissions between users from server and personal computer are not shared. – Adam Jul 04 '20 at 08:43
45

We've run into many edge cases when setting up permissions for Laravel applications. We create a separate user account (deploy) for owning the Laravel application folder and executing Laravel commands from the CLI, and run the web server under www-data. One issue this causes is that the log file(s) may be owned by www-data or deploy, depending on who wrote to the log file first, obviously preventing the other user from writing to it in the future.

I've found that the only sane and secure solution is to use Linux ACLs. The goal of this solution is:

  1. To allow the user who owns/deploys the application read and write access to the Laravel application code (we use a user named deploy).
  2. To allow the www-data user read access to Laravel application code, but not write access.
  3. To prevent any other users from accessing the Laravel application code/data at all.
  4. To allow both the www-data user and the application user (deploy) write access to the storage folder, regardless of which user owns the file (so both deploy and www-data can write to the same log file for example).

We accomplish this as follows:

  1. All files within the application/ folder are created with the default umask of 0022, which results in folders having drwxr-xr-x permissions and files having -rw-r--r--.
  2. sudo chown -R deploy:deploy application/ (or simply deploy your application as the deploy user, which is what we do).
  3. chgrp www-data application/ to give the www-data group access to the application.
  4. chmod 750 application/ to allow the deploy user read/write, the www-data user read-only, and to remove all permissions to any other users.
  5. setfacl -Rdm u:www-data:rwx,u:deploy:rwx application/storage/ to set the default permissions on the storage/ folder and all subfolders. Any new folders/files created in the storage folder will inherit these permissions (rwx for both www-data and deploy).
  6. setfacl -Rm u:www-data:rwX,u:deploy:rwX application/storage/ to set the above permissions on any existing files/folders.
Chris Schwerdt
  • 1,141
  • 9
  • 9
  • 4
    This is the only answer that uses ACLs and like the author said, this is what I also found to be the only "sane and secure" solution for setting up Laravel. Really appreciating this answer. – Sven Aug 03 '20 at 23:32
  • Shouldn't the -R flag be added to commands 3 and 4? – sakinobashi Feb 25 '21 at 11:01
  • There's no need to change the permissions of all the subdirectories/files because users/groups without execute permission on the top-level application folder will not be able to access any data within that directory or subdirectories (even if a subdirectory/file was `777`). See [this question and answer](https://unix.stackexchange.com/questions/13858/do-the-parent-directorys-permissions-matter-when-accessing-a-subdirectory) for details. – Chris Schwerdt Mar 02 '21 at 19:37
  • Isn't the default umask 0002? Should I just create a "deploy" user and set its umask to 0022? – Kevin Wheeler Aug 30 '22 at 00:08
  • Does this answer need to be updated to also run the `setfacl` commands on `bootstrap/cache`? – Kevin Wheeler Sep 07 '22 at 00:17
  • Btw, when uploading a file to application/storage/ using sftp, it was inheriting the permissions of the source file, well at least as far as the traditional permissions go. The file I had didn't have group read access set, so regardless of the ACL permissions, the www-data user was not able to read the file. I just chmod'ed the file g+x manually to fix it. I haven't thought through whether or not you could use the setgid bit and also change the group of application/storage to www-data to prevent this. – Kevin Wheeler Aug 16 '23 at 14:06
37

This worked for me:

cd [..LARAVEL PROJECT ROOT]
sudo find . -type f -exec chmod 644 {} \;
sudo find . -type d -exec chmod 755 {} \;
sudo chmod -R 777 ./storage
sudo chmod -R 777 ./bootstrap/cache/

Only if you use npm (VUE, compiling SASS, etc..) add this:

sudo chmod -R 777 ./node_modules/

What it does:

  • Change all file permissions to 644
  • Change all folder permissions to 755
  • For storage and bootstrap cache (special folders used by laravel for creating and executing files, not available from outside) set permission to 777, for anything inside
  • For nodeJS executable, same as above

Note: Maybe you can not, or don't need, to do it with sudo prefix. it depends on your user's permissions, group, etc...

Luca C.
  • 11,714
  • 1
  • 86
  • 77
26

Change the permissions for your project folder to enable read/write/exec for any user within the group owning the directory (which in your case is _www):

chmod -R 775 /path/to/your/project

Then add your OS X username to the _www group to allow it access to the directory:

sudo dseditgroup -o edit -a yourusername -t user _www
Bogdan
  • 43,166
  • 12
  • 128
  • 129
  • When I do `dseditgroup` provided by you, I'm getting an error: `Username and password must be provided.`. – Robo Robok Jun 04 '15 at 09:11
  • My mistake, you need to run that command with a user that has appropriate permissions, so just add `sudo` at the beginning. – Bogdan Jun 04 '15 at 09:18
  • So do I need to change owner of those files to `_www:_www` or `myuser:_www` as well? – Robo Robok Jun 04 '15 at 09:26
  • You can leave it `_www:_www`, because 775 means any user in the group `_www` will have full permissions to read/write/exect in that folder, and you just added your username to that group. – Bogdan Jun 04 '15 at 09:28
  • Could you tell me one thing? What does it mean `chown myuser:_www`? I know the first one is the user and the second one is the group, but does it mean "this user AND ANYONE FROM this group" or "this user BUT ONLY IF HE BELONGS TO this group"? – Robo Robok Jun 04 '15 at 09:30
  • **Any** user in the group `_www` will have full permissions to read/write/exec in that folder. – Bogdan Jun 04 '15 at 09:37
  • OK, so I tried `chmod go-rwx` on one folder. It set permissions to read/write for `_www` group and no access for `everyone`. Even though I now belong to `_www` group, I can't access those files from Finder. Why is that? – Robo Robok Jun 04 '15 at 09:48
  • If I leave owner to `_www:_www`, I'm unable to make any changes from the Finder without typing password. – Robo Robok Jun 04 '15 at 09:59
  • You need to also set execute permissions for the group on the given directory in order to have correct access to it. Read and write are not enough. That's why I wrote `775` not `765`. I've just tested this scenario myself and it works without any problems. – Bogdan Jun 04 '15 at 10:37
  • could you please update your answer to explain it in more detailed way, step by step? I want to make my web server `/Documents` to have only as little permissions as required. I think `775` on all files and folders is too much, isn't it? – Robo Robok Jun 04 '15 at 14:12
  • Plus, is `775` needed? Isn't `770` enough? – Robo Robok Jun 04 '15 at 15:11
  • Have a look at [this answer](http://serverfault.com/a/357109/158378), it explains in detail how you should approach the web server permissions conundrum. I'm curious though, is your web server accessible remotely? Because otherwise there's no real need for all these permission restrictions if it's a local/development web server. – Bogdan Jun 05 '15 at 09:59
  • My web server is not accessible remotely, it's just my local development environment. :) – Robo Robok Jun 05 '15 at 14:58
21

The Laravel 5.4 docs say:

After installing Laravel, you may need to configure some permissions. Directories within the storage and the bootstrap/cache directories should be writable by your web server or Laravel will not run. If you are using the Homestead virtual machine, these permissions should already be set.

There are a lot of answers on this page that mention using 777 permissions. Don't do that. You'd be exposing yourself to hackers.

Instead, follow the suggestions by others about how to set permissions of 755 (or more restrictive). You may need to figure out which user your app is running as by running whoami in the terminal and then change ownership of certain directories using chown -R.

This is what worked for me:

cd /code/laravel_project
php artisan cache:clear
php artisan config:clear
sudo service php7.4-fpm stop
sudo service nginx stop

sudo chown -R $USER:www-data storage
sudo chown -R $USER:www-data bootstrap/cache
chmod -R 775 storage
chmod -R 755 bootstrap/cache
sudo service php7.4-fpm start && sudo service nginx start


inspired by https://stackoverflow.com/a/45673457/470749


If you do not have permission to use sudo as so many other answers require...

Your server is probably a shared host such as Cloudways.

(In my case, I had cloned my Laravel application into a second Cloudways server of mine, and it wasn't completely working because the permissions of the storage and bootstrap/cache directories were messed up.)

I needed to use:

Cloudways Platform > Server > Application Settings > Reset Permission

Then I could run php artisan cache:clear in the terminal.

Ryan
  • 22,332
  • 31
  • 176
  • 357
16

Most folders should be normal "755" and files, "644"

Laravel requires some folders to be writable for the web server user. You can use this command on unix based OSs.

sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache
Siddharth
  • 369
  • 3
  • 7
13

I also follow the way to have user as owner, and user is member of www-data.

My sequence of command is a bit different:

cd /var/www/html/laravel-project-root 
sudo chown -R $USER:www-data .

sudo find . -type f -exec chmod 664 {} \;   
sudo find . -type d -exec chmod 775 {} \;

sudo find . -type d -exec chmod g+s {} \;  <----- NOTE THIS

sudo chgrp -R www-data storage bootstrap/cache 
sudo chmod -R ug+rwx storage bootstrap/cache

Please note the particularity of this very answer: I am the only (here) adding the group bit to every folder. In this way, if someone or something creates a new subfolder, it automatically has www-data as group

this happens when we are forced to deploy some userland files, preloaded using ftp, and so new subfolders folders are always owned from www-data group even if created by ftp client

Note also that the

sudo chgrp -R www-data storage bootstrap/cache >

is not needed if you do ALL of the commands in the list. But if you want to fix a ftp deploy, for example, and you didn't execute the 2nd line, so this is needed.

realtebo
  • 23,922
  • 37
  • 112
  • 189
11

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
markdwhite
  • 2,360
  • 19
  • 24
11

Add to composer.json

"scripts": {
    "post-install-cmd": [
      "chgrp -R www-data storage bootstrap/cache",
      "chmod -R ug+rwx storage bootstrap/cache"
    ]
}

After composer install

Davron Achilov
  • 536
  • 4
  • 14
  • 5
    This is a bad answer. You should never ever need to use 777 for any folder if you've configured the webserver correctly. Using 777 opens up your server for any hacker to upload a file, and execute said file if they know where the folder exists. – mbozwood Nov 09 '18 at 09:34
  • 2
    Okay. What are you offering? – Davron Achilov Nov 09 '18 at 11:50
  • And if so, will it be right? chown -R $USER:www-data storage, chown -R $USER:www-data bootstrap/cache – Davron Achilov Nov 09 '18 at 11:52
  • See the correct answer, it contains all the necessary information that you can absolutely put in the post-update :) – mbozwood Nov 09 '18 at 13:19
10

As posted already

All you need to do is to give ownership of the folders to Apache :

but I added -R for chown command: sudo chown -R www-data:www-data /path/to/your/project/vendor sudo chown -R www-data:www-data /path/to/your/project/storage

  • 3
    Why do we have to give permission to vendor directory? Storage make sense, to write to log files, etc. But vendor? why? – haris Sep 18 '16 at 05:37
  • As wrote above in some comment: "However, both your computer and your server Apache need to be able to write in these folders. Ex: when you run commands like php artisan, your computer needs to write in the logs file in storage." – Stanislav Potapenko Nov 15 '16 at 15:32
  • Error on mac: chown: www-data: illegal group name – Sunil Kumar Apr 06 '18 at 08:55
  • Please see https://stackoverflow.com/questions/8035939/write-privileges-localhost-mac-osx – Stanislav Potapenko Apr 18 '18 at 15:16
4

I have installed laravel on EC2 instance and have spent 3 days to fix the permission error and at last fixed it. So I want to share this experience with other one.

  1. user problem When I logged in ec2 instance, my username is ec2-user and usergroup is ec2-user. And the website works under of httpd user: apache: apache so we should set the permission for apache.

  2. folder and file permission A. folder structure first, you should make sure that you have such folder structure like this under storage

    storage

    • framework
      • cache
      • sessions
      • views
    • logs The folder structure can be different according to the laravel version you use. my laravel version is 5.2 and you could find the appropriate structure according to your version.

B. permission At first, I see the instructions to set 777 under storage to remove file_put_contents: failed to open stream error. So i setup permission 777 to storage chmod -R 777 storage But the error was not fixed. here, you should consider one: who writes files to storage/ sessions and views. That is not ec2-user, but apache. Yes, right. "apache" user writes file (session file, compiled view file) to the session and view folder. So you should give apache to write permission to these folder. By default: SELinux say the /var/www folder should be read-only by the apache deamon.

So for this, we can set the selinux as 0: setenforce 0

This can solve problem temporally, but this makes the mysql not working. so this is not so good solution.

You can set a read-write context to the storage folder with: (remember to setenforce 1 to test it out)

chcon -Rt httpd_sys_content_rw_t storage/

Then your problem will be fixed.

  1. and don't forget this composer update php artisan cache:clear

    These commands will be useful after or before.

    I hope you save your time. Good luck. Hacken

Hacken Lee
  • 49
  • 2
  • Did you try to call a command line script from Web server? I am having issue as it does not print any output – Volatil3 Apr 11 '18 at 10:48
  • hi i am using nginx but laravel creates new file with apache user :) how do i change this . new file created should use the nginx user – mrtechmaker Jan 09 '23 at 19:02
4

I have used this snippet for more than 3 years.


laravel new demo 

cd demo 

sudo find ./ -type f -exec chmod 664 {} \;    
sudo find ./  -type d -exec chmod 775 {} \;

sudo chgrp -Rf www-data storage bootstrap/cache
sudo chmod -Rf ug+rwx storage bootstrap/cache
sudo chmod -Rf 775 storage/ bootstrap/

php artisan storage:link

And @realtebo recommendation looks good. I will try.

sudo find . -type d -exec chmod g+s {} \;  <----- NOTE THIS
bingglex
  • 185
  • 4
  • 8
2

we will give 755 permission to storage and bootstrap folder permission

sudo chmod -R 755 bootstrap/cache
sudo chmod -R 755 storage

Solution 2 We will give all files and folder ownership to the webserver user

sudo chown -R www-data:www-data /var/www/your-project-path

set 644 permission for all files and 755 for all directories.

sudo find /var/www/your-project-path -type f -exec chmod 644 {} \; 
sudo find /var/www/your-project-path -type d -exec chmod 755 {} \; 

we will give proper read and write permission for files and folders.

cd /var/www/your-project-path
sudo chgrp -R www-data storage bootstrap/cache 
sudo chmod -R ug+rwx storage bootstrap/cache 

above all detail for ubuntu server

1

This was written in 2017 for around version 5.1~5.2. Use some common sense before you use this on later versions of Laravel.

I decided to write my own script to ease some of the pain of setting up projects.

Run the following inside your project root:

wget -qO- https://raw.githubusercontent.com/defaye/bootstrap-laravel/master/bootstrap.sh | sh

Wait for the bootstrapping to complete and you're good to go.

Review the script before use.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Jonathan
  • 10,936
  • 8
  • 64
  • 79
0

I had the following configuration:

  • NGINX (running user: nginx)
  • PHP-FPM

And applied permissions correctly as @bgies suggested in the accepted answer. The problem in my case was the php-fpm's configured running user and group which was originally apache.

If you're using NGINX with php-fpm, you should open php-fpm's config file:

nano /etc/php-fpm.d/www.config

And replace user and group options' value with one NGINX is configured to work with; in my case, both were nginx:

... ; Unix user/group of processes ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. ; RPM: apache Choosed to be able to access some dir as httpd user = nginx ; RPM: Keep a group allowed to write in log dir. group = nginx ...

Save it and restart nginx and php-fpm services.

Amirreza Nasiri
  • 536
  • 5
  • 14
0

For Laravel developers, directory issues can be a little bit pain. In my application, I was creating directories on the fly and moving files to this directory in my local environment successfully. Then on server, I was getting errors while moving files to newly created directory.

Here are the things that I have done and got a successful result at the end.

  1. sudo find /path/to/your/laravel/root/directory -type f -exec chmod 664 {} \;
    sudo find /path/to/your/laravel/root/directory -type d -exec chmod 775 {} \;
  2. chcon -Rt httpd_sys_content_rw_t /path/to/my/file/upload/directory/in/laravel/project/
  3. While creating the new directory on the fly, I used the command mkdir($save_path, 0755, true);

After making those changes on production server, I successfully created new directories and move files to them.

Finally, if you use File facade in Laravel you can do something like this: File::makeDirectory($save_path, 0755, true);

Mycodingproject
  • 1,031
  • 1
  • 9
  • 13
0

I'd do it like this:

sudo chown -R $USER:www-data laravel-project/ 

find laravel-project/ -type f -exec chmod 664 {} \;

find laravel-project/ -type d -exec chmod 775 {} \;

then finally, you need to give webserver permission to modify the storage and bootstrap/cache directories:

sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache
Sumit Wadhwa
  • 2,825
  • 1
  • 20
  • 34
0

If you have some code changes in some files and then some permission changes, it might be easier to set up the right permissions and commit again than try to pick the files that have permission changes. You will only be left with the code changes.

alex toader
  • 2,300
  • 1
  • 17
  • 20
-1

I found an even better solution to this. Its caused because php is running as another user by default.

so to fix this do

sudo nano /etc/php/7.0/fpm/pool.d/www.conf

then edit the user = "put user that owns the directories" group = "put user that owns the directories"

then:

sudo systemctl reload php7.0-fpm

  • *If* the visitor to the webpage manages to break out of the webserver, they will now have the access rights of the "user that owns the directories". If that user is www-data, there is a limited amount of damage they can do, and this is why apache runs as a limited user. If that user is not so limited, they can do more damage. If that user has sudo rights, they can do much more damage. – markdwhite Nov 15 '17 at 04:09
  • It's the same deal with apache. BTW I run nignx like a big boy now – CecilMerrell aka bringrainfire Nov 15 '17 at 17:31
  • 1
    This did work for me. i am using nginx and php-fpm had user as apache so new user was being created with apache user – mrtechmaker Jan 09 '23 at 19:07
-1
sudo chown -R $USER:www-data your_directory_name_under_storage_app

It will give required permission to server user & server for file access.

Ranjan Fadia
  • 1,363
  • 1
  • 14
  • 18
-1

Mac OS Big Sur

  1. In my case artisan couldn't access
    /var/www/{project_name}/storage
    to create files ex. in /logs folder so I had manually to go to /var and create the structure of folders that Laravel need to make symlink.

  2. Add access to folder sudo chgrp -R $USER /var/www/project_name

  3. Then I could use php artisan storage:link without any problems.

devzom
  • 676
  • 1
  • 9
  • 19