Proper permissions for web server's directory

  • Posted September 15, 2014

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

This comment has been deleted

@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

@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?

Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

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: /var/www/user1/html /var/www/user2/html /var/www/proyect1/html

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.

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.

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


“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

I’ve set up an Apache web server on Ubuntu 18.04. I faced permission problems running the webserver which is run by user www-data and files are owned by FTP user. After having trying different combinations for days. I think the best solution is to use

To install: apt-get install apache2-mpm-itk

Then inside your directive of the host you assign user and group as below.

<VirtualHost *:80> ServerName DocumentRoot /var/www/ Options -Indexes AssignUserID myusername mygroup </VirtualHost>

Now with myusername you can use SSH, SFTP, Rysnc and since the Apache will be run as myusernam, you won’t face any permission problems

Not recommented: Method 1. Another Solution I tried is to run the Apache webserver as user ‘myusername’, with this you can also avoid permission issue as you are also uploading the file with same user ‘myusername’ over SFTP. But the problem here is when you login over SSH with ‘myusername’ and after a while when you log out, Apache process is also terminated and with that website also goes down. But here I’ve a question at the bottom, would be glad if some one can explain.

Method 2. Assign user ‘myusername’ a group of www-data, same as that of Apache. Make everything inside /var/www/ own by user myusername and group: www-data chown -R myusername:www-data /var/www Make group has read, write, exec permission and set group id=2, which apply the group (www-data) to all new files/folders created in /var/www. chmod 2775 /var/www Most important part and nasty thing you have to do is change the unmask for the user ‘myusername’. Add unmask 0002 in .profile file inside your home directory.

I hope someone finds it useful. Now my question to the Method 1, I have decribed above. When the user: myusername logs out of ssh it also stop the apache webserver. But it don’t happen with the user: www-data!! Just to test I’ve made the user www-data also logable from terminal. After loggin in with user www-data over ssh and logging out, the apache webserver is still running. Why?


That’s how I was able to accomplish serving user-owned files from a user’s directory… I’m pretty sure this is how it is accomplished with WHM / cPanel.

There is a post “How To Host Multiple Websites Securely With Nginx And Php-fpm On Ubuntu 14.04” that includes a step for configuring PHP-FPM with user-specific pools.

I just copied the default /etc/php-fpm.d/www.conf to /etc/php-fpm.d/user.conf and updated a few values (note that I am using nginx for my setup - this should be replaced with the web server user, such as www-data):

user = user
group = user

listen = /run/php-fpm/user.sock
listen.owner = nginx = nginx
listen.acl_users = nginx
listen.allowed_clients =

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

slowlog = /var/log/php-fpm/user-slow.log

php_admin_value[error_log] = /var/log/php-fpm/user-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/fpm/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/fpm/wsdlcache

From there you just have to configure your (virtual) server to send PHP requests to your socket.


I’m new in Digital Ocean and I successfully created droplet and set up an apache2 server I uploaded all my website files in var/www/html folder but while accessing my website I am getting " This Page isn’t working error" Droplet IP -

Hi. What I do to achieve read / write on the /var/www directory is, beside doing all the solutions given in above I like to set ACL’s on the directory, which solves my read/write problem for particular user.

For example :

setfacl -d -R -m u:amol:rwx /var/www

-d : Default ACL permissions applied on new files -R : Apply the ACL permissions recursively -m : To set permissions

Hope this will help. :)

I realize this is an old post, but it is one of the top search results on Google and I don’t feel like it has been adequately answered anywhere (lots of meandering to getting to the point). So I wrote a blog post on the topic:

To summarize, the best balance between security and usability is to make the web root owned by root, create and assign a specific group to the web root, chmod 775 the web root, chmod g+s on the web root, and assign all users who need to edit files to the newly created group.

addgroup sftp-users
adduser youruser sftp-users
adduser anotheruser sftp-users

chown root /var/www
chgrp sftp-users /var/www
chmod 775 /var/www
chmod g+s /var/www

The g+s sets the “sticky bit” for the group, which correctly propagates the group and the permissions to all files (they’ll be 664) and directories (775) as they are created. The number of directories that need ‘www-data’ as the owner should be kept to a bare minimum.