This is a Canonical Question about File Permissions on a Linux web server.

I have a linux web server running apache2 the server hosts several websites Each website has its own folder in /var/www/.

/var/www/contoso.com/
/var/www/contoso.net/
/var/www/fabrikam.com/

The base directory varwww is owned by rootroot Apache is running as www-data:www-data. The website fabrikam is run by two developers alice and bob The two contoso websites are managed by one developer eve All websites permit users to upload pictures If the website is compromised the impact should be as limited as possible

Tell me the best way to set up permissions so that apache can serve the content the site is secure from attacks and developers can still make changes One of these websites is structured like this

/var/www/fabrikam.com
    /cache
    /modules
    /styles
    /uploads
    /index.php

What permissions should be set on these files and directories? I read somewhere that you shouldn't use 777 permissions on a website but i don't understand what problems that could cause During busy times the website automatically caches some pages and stores the results in the cache folder All the content submitted by website visitors is saved in the uploads folder

Best Answer


When you decide what permissions you need to use you have to know exactly who your users are and what they need A webserver interacts with two types of users

Authenticated users have a user account on the server and can be provided with specific privileges. This usually includes system administrators, developers, and service accounts. They usually make changes to the system via ssh or sftp

Anonymous users are the visitors to your website. Although they don't have the privileges to access files directly they can request a web page and the web server acts on their behalf You can restrict the access of anonymous users by being careful about what permissions the web server process has On many Linux distributions, Apache runs as the www-data user but it can be different. Use ps aux | grep httpd or ps aux | grep apache to see what user Apache is using on your system.


Notes on linux permissions

Linux and other posix-compliant systems use traditional unix privileges There is an excellent article on Wikipedia about Filesystem permissions so I won't repeat everything here. There are some things you should be aware of

The execute bit
Interpreted scripts (eg. Ruby, PHP) work just fine without the execute permission. Only binaries and shell scripts need the execute bit. In order to traverse (enter) a directory, you need to have execute permission on that directory. The webserver needs this permission to list a directory or serve any files inside of it.

Default new file permissions
When a file is created, it normally inherits the group id of whoever created it. But sometimes you want new files to inherit the group id of the folder where they are created, so you would enable the SGID bit on the parent folder.

The default permissions depend on your umask Umask subtracts permissions from newly created files so the common value of 022 results in files being created with 755 permissions When working with a group it's useful to change your umask to 002 so that files you create can be modified by the group members If you want to customize the permissions of uploaded files you either need to change the umask for apache or run chmod after the file has been uploaded


The problem with 777

When you chmod 777 your website, you have no security whatsoever. Any user on the system can modify or delete a file in your website Remember that the web server acts on behalf of the visitors to your website and now the web server can change the same files it executes There are various programming vulnerabilities in your website and they can be exploited to deface your website insert phishing attacks or steal information from your server without you knowing

Additionally, if your server runs on a well-known port (which it should to prevent non-root users from spawning listening services that are world-accessible), that means your server must be started by root (although any sane server will immediately drop to a less-privileged account once the port is bound). In other words, if you're running a webserver where the main executable is part of the version control (e.g. a CGI app), leaving its permissions (or, for that matter, the permissions of the containing directory, since the user could rename the executable) at 777 allows any user to run any executable as root.


Define the requirements

  • Developers need read/write access to files so they can update the website
  • Developers need read/write/execute on directories so they can browse around
  • Apache needs read access to files and interpreted scripts
  • Apache needs read/execute access to serveable directories
  • Apache needs read/write/execute access to directories for uploaded content

Maintained by a single user

If only one user is responsible for maintaining the site, set them as the user owner on the website directory and give the user full rwx permissions. Apache still needs access so that it can serve the files, so set www-data as the group owner and give the group r-x permissions.

In your case, Eve, whose username might be eve , is the only user who maintains contoso.com .

chown -R eve contoso.com/
chgrp -R www-data contoso.com/
chmod -R 750 contoso.com/
chmod g+s contoso.com/
ls -l
drwxr-s--- 2 eve      www-data   4096 Feb  5 22:52 contoso.com

If you have folders that need to be writable by apache, you can just modify the permission values for the group owner so that www-data has write access.

chmod g+w uploads
ls -l
drwxrws--- 2 eve      www-data   4096 Feb  5 22:52 uploads

The benefit of this configuration is that it becomes harder but not impossible for other users to snoop around on the system as only the user and group owner can browse your website directory This is useful if you have sensitive configuration files in your files Be careful about your umask! If you create a new file here the permissions will probably default to 755 You can run umask 027 so that new files default to 640 ( rw- r-- --- ).


Maintained by a group of users

If more than one user maintains the site you will need to create a group to use for assigning permissions It's good practice to create a separate group for each website and name the group after the website

groupadd dev-fabrikam
usermod -a -G dev-fabrikam alice
usermod -a -G dev-fabrikam bob

In the previous example, we used the group owner to give privileges to apache, but now that is used for the developers group. Since the user owner is no longer useful to us setting the username to root is a simple way to ensure that no privileges are leaked Apache still needs access so we give access to the rest of the world

chown -R root fabrikam.com
chgrp -R dev-fabrikam fabrikam.com
chmod -R 775 fabrikam.com
chmod g+s fabrikam.com
ls -l
drwxrwxr-x 2 root     dev-fabrikam   4096 Feb  5 22:52 fabrikam.com

If you have folders that need to be writable by apache, you can make apache either the user owner or the group owner. In either case it will have all the access it needs Personally i prefer to make it the user's owner so that the developers can still browse and modify the contents of upload folders

chown -R www-data uploads
ls -l
drwxrwxr-x 2 www-data     dev-fabrikam   4096 Feb  5 22:52 uploads

This is a common approach there is a downside Since the other user has the same privileges as apache it's easy for other users to browse your site and read files which may contain secret information like your configuration files

You can have your cake and eat it too

This can be improved upon further It's perfectly legal for the owner to have less privileges than the group, so instead of wasting the user owner by assigning it to root, we can make apache the user owner on the directories and files in your website. This is a reverse scenario of the single-maintainer scenario but it works equally well

chown -R www-data fabrikam.com
chgrp -R dev-fabrikam fabrikam.com
chmod -R 570 fabrikam.com
chmod g+s fabrikam.com
ls -l
dr-xrwx--- 2 www-data  dev-fabrikam   4096 Feb  5 22:52 fabrikam.com

If you have folders that need to be writable by apache, you can just modify the permission values for the user owner so that www-data has write access.

chmod u+w uploads
ls -l
drwxrwx--- 2 www-data  dev-fabrikam   4096 Feb  5 22:52 fabrikam.com

One thing to be careful about with this solution is that the owner of the new files will have the same owner as the creator instead of being set to www Thus any new files that you create won't be read by apache until you chown them


*Apache privilege separation

I said before that it's actually possible for other users to snoop on your website no matter what kind of privileges you use By default, all apache processes run as the same www-data user, so any apache process can read files from all other websites configured on the same server, and sometimes even make changes. The users who can get apache to run a script can gain the same access as apache itself

To combat this problem, there are various approaches to privilege separation in Apache. However each approach comes with various performance and security drawbacks In my opinion any site with higher security requirements should be run on a dedicated server instead of virtualhosts on a shared server


Additional considerations

I've never mentioned this before but it's generally a bad practice to have developers editing the site directly For larger sites you're much better off with some kind of release system that updates the webserver from the contents of a version control system The single maintainer approach is probably ideal, but instead of a person you have automated software.

If your website allows uploads that don't need to be served that uploads should be stored somewhere outside the root You might find that people are downloading files that were supposed to be secret For example if you allow students to submit assignments they should be saved to a directory that is not served by apache This is also a good approach for configuration files that contain secrets

For a website with more complex requirements, you may want to look into the use of Access Control Lists . These enable far more sophisticated control of privileges

If your website has complex requirements you may want to write a script that sets up all the permissions Test it thoroughly and then keep it safe This could be worth a lot of gold if you ever need to rebuild your website