Wednesday, March 27, 2013

Apache Virtual Hosts - permissions

Apache Virtual Hosts - permissions


One thing that can cause concern and configuration headaches is virtual hosts permissions.

Using the multiple hosts layout in this article is a good way of keeping your domains in one place and with easy access. Let's take a look at the permissions of the folders.




Reminder


A quick reminder of the layout used in these articles:

All the vhosts directories are place in the user's home directory under public_html. Each domain has it's own directory with a 'standard' set of folders such as public, private, logs, cgi-bin, backup and so on.

The multiple hosts layout article has some images to show the layout in detail.

Users


We have to think of who will want access to the folders. There are two users to consider.

The first is the Slice user - in this case my username is 'demo'. It is in demo's home directory that the public_html directory is placed.

Secondly is the Apache user. On Debian based systems it is usual for Apache to be 'www-data' and be in the 'www-data' group. Other Linux distributions use the user 'nobody' or even 'apache'.

Access


Now we need to think about what actions will need to be taken by what user.

Apache needs to be able to enter the public_html folder and to be able to read the public and private directories.

The logs are written by the 'parent' Apache process which is root so we don't have to worry about that (root will have access to the logs directory anyway - all other Apache processes are completed by the child process which will be 'www-data' or 'nobody').

Write access


OK, but what happens if Apache needs write access? An example of this would be uploading images or files.

One way would be to allow world write access to the folder (setting the permissions at 777). The problem with this is that the world has write access to the folder.

Even if you had a specific upload folder and were careful with your scripts, it still leaves a 777 folder exposed to the public.

Groups


Remember the layout being used is for single user Slices. I host many websites on one Slice and I am the only one who has access to it.

What if we placed the main user (demo) in the 'www-data' group? That way, any folder that Apache needs to write to, such as the image upload folder, would only need 770 permissions.

There is no need for any other system user to access those folders. This also stops the practice of having a folder with 777 permissions.

User setup


So let's start by adding the main user to the Apache user group:
sudo usermod -a -G www-data demo

That adds the user 'demo' to the 'www-data' group. Do ensure you use both the -a and the -G options with the usermod command shown above.

You will need to log out and log back in again to enable the group change.

Check the groups now:
groups
...
# demo www-data

So now I am a member of two groups: My own (demo) and the Apache group (www-data).

Folder setup


Now we need to ensure the public_html folder is owned by the main user (demo) and is part of the Apache group (www-data).

Let's set that up:
sudo chgrp -R www-data /home/demo/public_html

As we are talking about permissions I'll add a quick note regarding the sudo command: It's a good habit to use absolute paths (/home/demo/public_html) as shown above rather than relative paths (~/public_html). It ensures sudo is being used in the correct location.

If you have a public_html folder with symlinks in place then be careful with that command as it will follow the symlinks. In those cases of a working public_html folder, change each folder by hand.

Setgid


Good so far, but remember the command we just gave only affects existing folders. What about anything new?

We can set the ownership so anything new is also in the 'www-data' group.

The first command will change the permissions for the public_html directory to include the "setgid" bit:
sudo chmod 2750 /home/demo/public_html

That will ensure that any new files are given the group 'www-data'. If you have subdirectories, you'll want to run that command for each subdirectory (this type of permission doesn't work with '-R'). Fortunately new subdirectories will be created with the 'setgid' bit set automatically.

If we need to allow write access to Apache, to an uploads directory for example, then set the permissions for that directory like so:
sudo chmod 2770 /home/demo/public_html/domain1.com/public/uploads

The permissions only need to be set once as new files will automatically be assigned the correct ownership.

DRY


This may get a bit tedious when you add new domains to your public_html folder.

In that case, I would create a 'skeleton' domain structure with the relevant permissions and simply copy it to the new domain:
cp -a /home/demo/public_html/skeleton /home/demo/public_html/my_new_domain

That way you have a nice and new set of folders with the correct permissions in one simple command.

Summary


Permissions are a sensitive topic and you do have to be careful with them. Don't just enter a 'chmod -R' command without thinking about the contents and symlinks.

I hope this helps alleviate concerns about vhosts and permissions.

I'd also like to thank Placid for his help in proof-reading this article - it was one I did not want to get wrong!

PickledOnion.

Addendum


A couple additions without changing too much of PickledOnion's article, based on user feedback:

Permissions in general


If you have more questions about how permissions work in Linux, you might take a look at this series on file permissions. It's a bit long, but thorough.

Setting a umask


The setgid bit allows files to inherit group ownership from the parent directory, but it doesn't affect their permissions. If you want new files to be created group-writeable by default instead of set that way manually, you need to change the umask.

You can find more information on using the umask command in this article. To give an example of a umask, "umask 002" would add group write permissions to new files.

If you want to set the umask for new files created by the web server, the file to change depends on the distribution and the software package. On Ubuntu or Debian you can add the umask line for apache in the file:
/etc/apache2/envvars

If you're running apache on CentOS, RHEL, or Fedora, you would add the umask command to:
/etc/sysconfig/httpd

No comments:

Post a Comment