Unix Permissions for Shared Directories

Do you work on a shared system where you are one of several people who needs to edit content in a shared directory? Or maybe you work on a Linux system where the static web content is in a shared directory owned by a system users (who's not you.) This latter case is the default for Apache or Lighttpd on Ubuntu. You may have encountered permissions problems when trying to edit files in these directories. This page describes a simple technique for changing permissions of a shared directories so a list of authorized users can edit its contents. As security boffins will tell you, this is preferred to making the directory "world writable" -- the last thing you need is a random internet troll defacing your web site.

What Are You Trying To Tell Me?

Simply put, there's an easy, safer way to make a directory (and its sub-directories) writable by a subset of system users.

Why Is This Useful?

While you should have a system in place to store your content in a version control system and then deploy that content to a real server somewhere on the internet, sometimes the world doesn't work that way. For instance, I sometimes want to test the behaviour of a browser locally on my Linux laptop or in a Linux virtual machine. I don't want to check a file into version control after every minor change and wait for it to be deployed. In this case I want to edit files directly in the web server's static content directory hierarchy.

But the default configuration for Ubuntu and Debian is to not allow this.

The steps below describe how to fix this.

If you follow these steps, you won't have to sudo to root to edit a file. Any tool you happen to use to create web-pages, whether it's a WYSIWYG tool like FirstPage or a text editor like Emacs, it should just work.

Details, Please.

Unix, Linux, Darwin, BSD -- all modern Unixes -- only allow you to write a new file to a directory if:

It's generally considered a bad idea to let anyone write content to a particular directory, so we should probably forget about that last item.

And we're not really interested in the first case because we're explicitly talking about shared directories; directories where multiple people can read and write files.

That leaves us with item number two: group ownership of files.

Debian (and it's commercial derivative Ubuntu) come pre-configured with a group called www-data. By default, new users aren't added to this group. When you install a web server like Apache or Lighttpd, you can change the group owner of it's static content directory to allow group writes. Then you just add yourself to www-data group, and change the group permissions on the shared directory and viola! you can write to the shared directory!

This example assumes your static web content is in the directory /var/www/html, which is where you find it on recent Ubuntu systems.

   $ sudo addgroup `whoami` www-data
   $ sudo chgrp -R www-data /var/www/html
   $ sudo find /var/www/html -type d -exec chmod 2775 {} \;
   $ sudo find /var/www/html -type f -exec chmod 0775 {} \;

Except it's not exactly that easy. Because of the way group permissions work in Linux, you have to log out and log back in. You could type the command su - `whoami` to test that it works, but that will give you a sub-shell that doesn't have the DISPLAY environment variable set, which could be a problem if you're using an X/Windows based editor.

After relogging-in, you can test that it works with the following commands:

  $ touch /var/www/html/foo
  $ ls -ld /var/www/html
  drwxrwsr-x 2 root www-data 4096 Mar 26 13:06 /var/www/html/
  $ ls -l /var/www/html/foo
  -rw-rw-r-- 1 you www-data 0 Mar 26 13:06 /var/www/html/foo

If you don't see -rw-rw-r-- in the last line of output above (specifically, if you see -rw-r--r-- ) make sure you're not issuing the touch command as the root user. Debian is supposed to default to a 0002 umask for normal users and 0022 for root. But you may need to manually change the file mode creation mask (umask) to 0002, like this:

   $ umask 022

The default umask used to be set in ~/.profile or /etc/profile and was easy to change. Unfortunately, there are a number of different places where the default umask is now set in Ubuntu, so your mileage may vary, but the command above will always work when issued from the command line.

Once you set this up, anyone in the www-data group will have permission to read, write and delete files in the shared directory, even if that directory is owned by the root user.

So What's Going On Here?

The real magic here is when we recursively set the SetGID bit on the shared directory and it's sub-directories. This is what the sudo find /var/www/html -type d -exec chmod 2775 {} \; command did. The SetGID bit tells the system to inherit the group owner of new files from the group owner of the directory it's created in. By setting the Write and SetGID bits, authorized users can edit files in this directory and permission to edit these files are automagically given to other members of the www-data group.

But remember, it's probably bad practice to log into web servers and edit files on the fly. Sure, sometimes you may have to do this in an emergency, but your process should involve storing changes in a version control system, having team-mates review the changes, and then have the changes deployed to your production systems with a continuous deployment system. The process described here should work fine on a development machine, however.