Permissions setup for a Debian web host

> This is another of those “note-to-self” posts, where I detail how I’m setting something up so that I can refer back to it, or so I can point someone else to it. As if often the case, some of this may be Debian-specific…

There are different ways of approaching the task of setting the permissions for web directories, depending on how many users have access to the server, how many sites are sharing the server, and lots of other concerns. I tend to be in a situation where anyone who has shell access to the server is at a level trusted with web content, so that simplifies the process somewhat. I’ll look at different levels of dealing with this questions, in increasing levels of security.

## Simplest approach: use the `www-data` group

This is the default group that Debian has for web daemons. If you add everyone who can log in to this group, you can then use this group for all web directories that the notional “web team” needs to access, and make them “group writable”. **Be aware that this configuration also allows the Apache daemon itself to write to the web directories, which is an obvious potential security issue, so you need to be sure that the web applications in there don’t/won’t allow that.**

You can either specify the group when creating the user:

adduser –ingroup www-data USER

or add an existing user to the group:

adduser USER www-data

## Almost as simple as simplest approach: create a `webdev` group

This is also a very simple approach, which won’t allow Apache to write to the web directories, unless you specifically allow it. (This would usually be for cache directories, image upload and so on.)

“webdev” is just an arbitrary name, it can be anything you like as long as it doesn’t exist. First create your new group, then add the user(s) to it:

addgroup webdev
adduser USER webdev

It goes without saying (or should do) that for the above to work, you also need to allow the right group access to the web directories you need. A simple example of this, making a few assumptions of your directory layout, would be:

chgrp -R webdev /www/www.example.com/htdocs
chmod -R g+w /www/www.example.com/htdocs

So what did we just do?

First, we recursively (`-R`) changed the group to be `webdev` for the `htdocs` directory. Then, we (also recursively) allowed the group write-access (`g+w`) on `htdocs`. Which means: from now on, anyone in the `webdev` group can create and edit files in `htdocs` and any of its subdirectories. Note that these lines will stop any previously configured group-access from working (if it’s a different group from `webdev`). However, if we have a directory with write-access for everyone (AKA “`chmod 777`”) as is sometimes the case with cache directories, for example, they won’t be affected.

So, how can we make this more granular?

## Multi-layered approach: create per-site groups

If we wanted to have some directories writable by all our web team, and others by certain people in certain sub-teams, we can create multiple groups.

Take, for example, two subdomain sites on example.com: foo.example.com and bar.example.com. Of course, these could be different domains, I’m just sticking with example.com for the, er, examples. We want to deny editing access to the teams working on these two sites to each other’s site. A solution is to create two groups: `webdev-foo` and `webdev-bar`, maybe.

addgroup webdev-foo
addgroup webdev-bar
adduser fooguy webdev-foo
adduser foogal webdev-foo
adduser barboy webdev-bar
chgrp -R webdev-foo /www/foo.example.com/htdocs
chgrp -R webdev-bar /www/bar.example.com/htdocs
chmod -R g+w /www/foo.example.com/htdocs /www/bar.example.com/htdocs

This takes care of giving write-access for their sites to `fooguy`, `foogal` and `barboy`. Neither `fooguy` nor `foogal` will be able to write to the bar.example.com site’s directory, and `barboy` won’t be able to edit foo.example.com. If we want to allow all three of them to edit or create inside the main site, we just add them to the `webdev` group, assuming we’ve already set the permissions for its root directory and children to be `g+w`.

adduser fooguy webdev
adduser foogal webdev
adduser barboy webdev

## Checking permissions

If we pop over and have a look at these directories, what should be see?

cd /www
ls -l *example.com

The output should be something like:

bar.example.com:
total 4
drwxrwxr-x 2 root webdev-bar 4096 2012-01-09 18:49 htdocs

foo.example.com:
total 4
drwxrwxr-x 2 root webdev-foo 4096 2012-01-09 18:49 htdocs

www.example.com:
total 4
drwxrwxr-x 2 root webdev 4096 2012-01-09 18:50 htdocs

What does that mean? What we’re seeing here is that in all cases, the permissions are set as `drwxrwxr-x`, which means:

1. It’s a directory
2. User permissions are `rwx` – Read/Write/eXecute
3. Group permissions are also `rwx`
4. Other (“world”) permissions are `r-x` – Read/eXecute

We can also see that each of the `htdocs` entries has `root` as its owner, and the respective group we set before as its group. If we’ve already got a super simple site in these – just an index and an image directory – and list inside of htdocs, we should see:

bar.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev-bar 4096 2012-01-09 19:01 img
-rw-rw-r– 1 root webdev-bar 0 2012-01-09 18:59 index.html

foo.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev-foo 4096 2012-01-09 19:01 img
-rw-rw-r– 1 root webdev-foo 0 2012-01-09 18:59 index.html

www.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev 4096 2012-01-09 19:01 img
-rw-rw-r– 1 root webdev 0 2012-01-09 18:59 index.html

This tells use that the index and the directory are both editable by the right groups as well. (Files are `-rw-rw-r–`, meaning user and group read/write and world read-only.)

*To clarify: “execute”, when applied to directories, means the ability to change into it or open it. Applied to a file, the execute-bit is a potential hazard, if the file has any code in there, but that’s another story for another day.*

## More granularity: ACL

The approach detailed above is usually enough for most web situations, but if more control is required, we move into ACL territory (Access Control Lists). This is something that has to be made available at the filesystem level, and isn’t usually available on normal web hosts. As such, it’s a bit out of the scope of this post.

Adding extra IP addresses to Debian

I was just asked to add a new IP address to a Debian cloud host. It’s a simple thing, but depending on how often – or how seldom – you do it, you often still need to look it up to remind yourself. So, having previously decided to do a post every time I do something like this (for my own benefit as much as anything) here’s what I did…

Edit `/etc/network/interfaces` – obviously you’ll need to be root or `sudo` it.

There will probably something like this in there:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

The first chunk is the [loopback interface](http://en.wikipedia.org/wiki/Loopback), but the second chunk is the ethernet (`eth0`). The final line might be `dhcp` or it might be `static`, followed by more lines to describe the IP, like this:

iface eth0 inet static
address 209.85.147.147
netmask 255.255.255.255

To add a new IP – let’s imagine it’s ‘209.85.147.148’ – to the same ethernet interface, just add something like this:

iface eth0:0 inet static
address 209.85.147.148
netmask 255.255.255.255

The “`:0`” is the extra bit we added. Then restart your networking:

/etc/init.d/networking restart

(keeping your fingers crossed you didn’t make any mistakes that might then lock you out of your host completely, of course ;)