So I have a directory in /var/www (called cake) and I need to allow www-data to write to it, but I also want to write to it (without having to use sudo). I'm afraid to change the permissions to 777 in case some other user on my machine (or a hacker) attempts to modify files in that directory. How do I only allow access for myself and Apache's www-data?
3 Answers
As stated in an article by Slicehost:
User setup
So let's start by adding the main user to the Apache user group:
sudo usermod -a -G www-data demo
That adds the user 'demo' to the 'www-data' group. Do ensure you use both the -a and the -G options with the usermod command shown above.
You will need to log out and log back in again to enable the group change.
Check the groups now:
groups ... # demo www-data
So now I am a member of two groups: My own (demo) and the Apache group (www-data).
Folder setup
Now we need to ensure the public_html folder is owned by the main user (demo) and is part of the Apache group (www-data).
Let's set that up:
sudo chgrp -R www-data /home/demo/public_html
As we are talking about permissions I'll add a quick note regarding the sudo command: It's a good habit to use absolute paths (/home/demo/public_html) as shown above rather than relative paths (~/public_html). It ensures sudo is being used in the correct location.
If you have a public_html folder with symlinks in place then be careful with that command as it will follow the symlinks. In those cases of a working public_html folder, change each folder by hand.
Setgid
Good so far, but remember the command we just gave only affects existing folders. What about anything new?
We can set the ownership so anything new is also in the 'www-data' group.
The first command will change the permissions for the public_html directory to include the "setgid" bit:
sudo chmod 2750 /home/demo/public_html
That will ensure that any new files are given the group 'www-data'. If you have subdirectories, you'll want to run that command for each subdirectory (this type of permission doesn't work with '-R'). Fortunately new subdirectories will be created with the 'setgid' bit set automatically.
If we need to allow write access to Apache, to an uploads directory for example, then set the permissions for that directory like so:
sudo chmod 2770 /home/demo/public_html/domain1.com/public/uploads
The permissions only need to be set once as new files will automatically be assigned the correct ownership.
Let's say you want to sftp into a directory sharing reading, writing and executing permissions with www-data, this is what you should do:
1 - Add yourself to www-data group
sudo usermod -a -G www-data <your_user>
2 - Sets the wanted user:group ownership for your folder and files recursively
sudo chown -R <your_user>:www-data <your_folder>
3 - This adds permissions (read write execute) to all users (a+rwx); Restrict permissions from others (o-rwx); Sets the same (folder inherited) user:group for every new file created under that directory (ug+s). This will be executed recursively and only in folder (probably exactly what you want)
sudo find <folder_name> -type d -exec chmod a+rwx,o-rwx,ug+s {} +