Apache DevCenter
oreilly.comSafari Books Online.Conferences.


Apache Cookbook

A Day in the Life of #Apache
Making Your Web Site More Welcoming

by Rich Bowen, coauthor of Apache Cookbook

Editor's note: In this latest article in the series based on his conversations on the IRC channel #apache, Rich Bowen walks through three error condition scenarios administrators have encountered and what to do about them, so you can create a more welcoming, less "Forbidden" web site for your users.

#apache is an IRC channel that runs on the irc.freenode.net IRC network. To join this channel, you need to install an IRC client (XChat, MIRC, and bitchx are popular clients) and enter the following commands:

/join #apache

Day Five

Returning to the theme of "Frequently Asked Questions" on #apache, this week we'll be talking about how to make your web site more welcoming.

<Lanman> When I try to load pages from my server, it won't let me.
<DrBacchus> Won't let you? What happens when you try?
<Lanman> Forbidden
<fajita> look in the error log or Directory permissions don't permit read, or index.html is missing and Options Indexes is not in effect, or Deny from all is in effect for the directory.

Now, that's distinctly unfriendly. But what does it mean?

Related Reading

Apache Cookbook
By Ken Coar, Rich Bowen

The problem is, as fajita implies, Forbidden can mean a number of things, depending on the context, and the only way to know for sure is to look in the error log. We'll look at several possible scenarios.

<DrBacchus> Lanman: What, verbatim, does the error log say?

(By the way, I should point out that when you spend much time on #apache, you'll notice that I utter exactly the same phrases repeatedly. That's because I have macros that say my common phrases for me, to save me from having to type things out again and again. In the case of the above statement, what I really typed was /err Lanman, and my IRC client filled in the rest.)

<Lanman> Permission denied: access to /foo/index.php failed because search permissions are missing on a component of the path

Not so long ago, someone went through all of the error messages that Apache emits, and improved them so that they gave more meaningful information in the event of an error condition. This particular error message got quite a bit of discussion at the time, because there was a desire to make it clear, but also to make it concise. I think that we succeeded, but it's possible that it's just a little bit too concise.

What "search permissions are missing on a component of the path" means is that somewhere in the directory path leading up to the file in question, there's a search (x) bit missing from one of the directories. You see, Apache needs to be able to look at files, the same as any other application does. And so it needs the search bit (x) set so that it can cd into a directory to get a look around.

In this case, the file in question is located at /usr/local/apache/htdocs/foo/index.html, and the components of the path are /usr, /usr/local, and so on.

<DrBacchus> What are the permissions on the directory containing that file? Type ls -lad /path/to/directory
<Lanman> drwx------ 2 root root 4096 Mar 22 21:07 /usr/local/apache/htdocs/foo
<DrBacchus> Oh, there's the missing search permissions. chmod 755 foo

For directories containing the web content, you need the read and execute permissions to be set. For a directory that Apache will just need to pass through on the way to a content directory, execute (search) permission is sufficient.

Thus, for web content running out of /home/waldo/public_html, for example, /home/waldo should be 711 (chmod 711 /home/waldo) and /home/waldo/public_html should be 755 (chmod 755 /home/waldo/public_html).

These file permission remarks are somewhat Unix-centric. You're somewhat unlikely to encounter this particular version of the Forbidden message on a Windows platform. For more details on what those numbers mean, you might want to check out the chmod tutorial at catcode.com/teachmod, or the mode calculator at wsabstract.com/script/script2/chmodcal.shtml.

Alas, there are other reasons for Forbidden warnings, which we see shortly afterwards.

<brainpan> I'm getting a Forbidden message. How do I fix that?
<Lanman> That's because your file permissions are not correct!
<DrBacchus> Not necessarily.
<DrBacchus> fajita: Forbidden?
<fajita> look in the error log or Directory permissions don't permit read, or index.html is missing and Options Indexes is not in effect, or Deny from all is in effect for the directory.
<DrBacchus> brainpan: What does your error log say?
<brainpan> [Tue Mar 23 12:25:43 2004] [error] [client] Directory index forbidden by rule: /usr/local/apache/htdocs/test/
<DrBacchus> You'll need a Options +Indexes for the directory in question, or you need a DirectoryIndex file for that directory.

In this case, what we have is a directory that does not contain a DirectoryIndex file -- that is, doesn't contain a default document. The default document, usually index.html, can be configured with the DirectoryIndex directive to be whatever you like, and is often set to index.php or index.cgi, for example.

When this file is missing, Apache tries to supply a directory listing instead. But this will only work if the Options Indexes setting is in force for that directory.

The solution for this version of Forbidden is to either place an index.html file in that directory, or add the following configuration block to your configuration file.

<Directory /usr/local/apache/htdocs/test>
  Options +Indexes

Finally, since there's yet another way to be Forbidden, we'll tackle that one now.

<BigMuscles> I'm getting a Forbidden message when I access my web site. What can I do to fix that?
<DrBacchus> What does your error log say?
<BigMuscles> [Tue Mar 23 12:38:38 2004] [error] [client] client denied by server configuration: /usr/local/apache/vhosts/cousineddie

Same message in the browser, but a different error message in the error log.

In this case, there's something in the configuration file that specifically states that clients can't get to the directory in question. Usually, this is the following:

<Directory />
  Order deny,allow
  deny from all

The goal of that configuration is to prohibit content outside of the document root from being loaded through the web server. The side effect is that for any directory (outside of the document directory) for which you want to load content, you must tell Apache to permit it. This is a simple matter of adding:

<Directory /usr/local/apache/vhosts/cousineddie>
  Order allow,deny
  Allow from all

As with any other Apache configuration, this applies to subdirectories as well. If you have a number of vhosts in /usr/local/apache/vhosts, for example, you could just create one Directory section for that directory, and have it apply to all those vhosts.

It is also possible to deny access from a particular address, or range of addresses, rather than from all, but, usually, when people experience this particular error condition, that's not what they're encountering.

Why do all of these different error conditions create the same browser error message? Well, the simple answer is that's all the end user needs to know. Telling the end user specifically why they were denied a resource is not good security policy. As the web server administrator, you should be looking in the error log, not in the browser, for useful error messages.

We'll close with an important word from fajita:

<DrBacchus> fajita: step one?
<fajita> Whatever the problem, step one is always to look in the error log.

A special thank you to mrnoir on #apache, who assisted me with proofreading, and made many excellent suggestions for the improvement of this article.

Check back next month as Rich helps resolve yet another common Apache dilemma.

Rich Bowen is a member of the Apache Software Foundation, working primarily on the documentation for the Apache Web Server. DrBacchus, Rich's handle on IRC, can be found on the web at www.drbacchus.com/journal.

O'Reilly & Associates recently (in November 2003) released Apache Cookbook.

Return to the Apache DevCenter.

Sponsored by: