Proper permissions for web server's directory

September 15, 2014 28.4k views

I have a doubt that I think is very basic but to which strangely I couldn't find a concrete answer no matter how much I've googled for it.

When configuring a web server (Nginx, in my case), most people recommend setting the permissions as follows:

  • Create a new user other than root, and add it to the www-data group.
  • Set the ownership of /var/www to the www-data user and www-data group.
  • Directories 755
  • Files 644

This means that:

  • The user owner of the directory (www-data) can read, write and execute.
  • The assigned group (www-data, where my user is) can read and execute, but not write.
  • Everyone else can read and execute, but not write.

The problem with this is that, if the permissions are set in this way, I can't edit files from the FTP because my user doesn't have write permissions; this would require allowing the group to write adjusting the permissions like this:

  • Directories 775
  • Files 664

However, I don't know if this could be a security issue, or why do people recommend doing it the other way if it doesn't work through FTP. So, what is the most appropriate way to set permissions for the server directory?

  • Does nginx use www-data as the user? I know apache does, but not sure about ngnix.

    In answer to your question: The tighter your permissions, the less likely you are to have problems. In other words, you always want to error on the side of caution.

    In college, my Networking Instructor said the rule of thumb is: only give users permissions where they need them.

    If you are working on a site, you can set things a little more relaxed, and then tighten your permissions when you have finished development.

    My experience is that there are some files you will edit, and then tighten permissions to 600 after editing. For example, if you are running WordPress, it is not necessary to grant 664 access to the configuration file (wp-config.php), since only the web-server needs access to that file.

    In summary:

    • while developing you can have your permissions at 775
    • after development, tighten your permissions as much as possible, especially on configuration files that may contain database passwords and such
  • @sierracircle: Thanks for your answer. Yes, Nginx works by default with the www-data user (for compatibility reasons with Apache, I think).

    I find a bit annoying changing the permissions each time I'm going to access by FTP, but certainly it would be good for security.

    I've seen that shared hostings usually have this set of permissions:

    • User/group: user:user
    • Directories: 755
    • Files: 644

    I don't know how they do it, but I guess they:

    • Create a new user for each of its customers with very restricted permissions.
    • Configure the server (either Apache, Nginx or otherwise) to work with that restricted user instead of the www-data user.

    This makes it possible to have the permissions as 755 and 644 while allowing full access by FTP and also with minimal risk.

    However, it's just an idea and I haven't seen anyone recommending doing it this way.

    Does anyone know if they really do like this and if it would be advisable to do so?

  • @sierracircle @ManuelFte

    how do you know what permission does that group/user have?
    and can you apply default permission for folders/files? or I have to do it manually?

    I have nginx and I didnt know what to do so:

    1. I created a new group called admin
    2. I added my user(not root) to admin group
    3. I changed the nginx/html folder's group to admin (html folder is the same as www in apache i think?)
    4. I changed the permission of html to 775 manually. so me and root (the owner) can only read/write/execute but the others (public) can only read/execute.
    5. and any file I add, I change the permission to 664
4 Answers


"how do you know what permission does that group/user have?"

from a command-line run:
id yourusername

it will return all of the groups that user belongs to

Is there an automated way to set these permissions properly for all folders?

So I've been thinking a lot about this lately, and something occurs to me.
There will only ever be one web server, but there could be multiple developers working on a website.

So instead of assigning the group to www-data, assign the user to www-data, and create a group dev-websitename and assign your development users to it.

Then you can easily give more permissions to the dev group, and restrict permissions to the owner. I don't see why "Other" users ever need any access what so ever.

Here's the code:

    sudo chown -R www-data:dev-mysitenamehere .
    sudo find . -type f -exec chmod 0460 {} \;
    sudo find . -type d -exec chmod 2570 {} \;

The 2 in the directory chmod makes it so files inherit the folder's group

Now, the issue here is when you create new files as your user, their owner will be your user name, not the server's name (www-data). But in some ways, this is ideal, forcing you to manually change the ownership of new files so that they are visible by the server. Of course you could always set git post.receive to do this for you too.

For "storage" folders or other folders the server needs access to you can use this mode so your server can also edit these files:

    sudo find storage -type f -exec chmod 0660 {} \;
    sudo find storage -type d -exec chmod 2770 {} \;

I have not sufficiently tested this method - it may be that there are downsides, but it just seems like it makes more sense to me. There will only be one server user, but there will be multiple developer users. So group makes sense for developers, while owner makes sense for the server, and other users have no business here.

I was poking for info on how ppl set their permissions, i have see a fair share of setups even on big shared hostings on many distributions.

The ones i liked are:
Webserver credentials: $webserveruser:www-data
user credentials : $username:$privateusergroup (same as username)
php pool credentials: same as user credentials.

Now for files:
Usually you have a root folder for the user (sort like homedir) and a root folder por serving web pages.
Something like:

Now, each "home dir" is owned by its own user, example /var/www/user2 is owned by user2:user2
Every subfolder too, exactly like a homedir, this is where many ppl get confused, how do you let the webserver read the files? (remember, php is using user credentials so it will always have full permissions on the working dir of the user, example, user2/html), Well..
Assign $webserveruser to each $privateusergroup, everytime you add an user, do:
usermod -aG $privateusergroup $webserveruser
not the other way around, its confusing because the privategroup has the same name as the user.
Now, you can set home dir to: chmod 710 /var/www/user2
and user2/html should have a default mask and permissions, example 75x, the root dir is already locked to others so it doesn't matter. The webserver should be able to traverse a serve files, the user should not have problems using ftp with default mask and permissions, and php should be able to edit and read user files. Other users wont be able to read the files.

The other solution is using ACLs, but in the end its the exact same thing as my solution above, as setfacl will set a mask on the group permissions when setting a particular user or group access, it means the 'extra' permissions ser using acl will be controlled using the group permissions 'mask', And the extra headche to manage ACLs on a server is not worth it in my exprience.

setguid and group traditionals groups like www-data are a problem when the owner of the root dir is the user as it can change or delete permissions.

If many users have to access proyect1 for example, ACLs can be used but i like to ser the owner of the proyect to a particular user or root, set a group for collaboration like $project1group, chmod g+s bit on that dir, set 770, and asign the $webserveruser and the users of the proyect to $project1group.

Have another answer? Share your knowledge.