I was bashing my head against the desk wondering why my virtual sites were giving a ‘Forbidden – You don’t have permission to access / on this server’ message after upgrading to Leopard, despite the file/directory permissions on the web directories being unchanged.

This happens if your virtual sites aren’t under /Library/WebServer/Documents and there is a solution that doesn\’t need the apache user and group to be changed (which could lead to other hassles).

After actually realising Leopard had changed from using Apache1.3 to Apache2 I (eventually) looked at what differences there were in the httpd.conf files relating to directory access.

(In what follows I’ll use square brackets to delimit apache directives in case angle brackets aren’t escaped when displaying as HTML).

In Apache1.3 Apple’s httpd.conf has this:

[Directory /]
Options FollowSymLinks
AllowOverride None
[/Directory]

[Directory “/Library/WebServer/Documents”]

Order allow,deny
Allow from all
[/Directory]

The [Directory /] block has an implicit Order Deny, Allow directive (i.e. the default) so that anything below the root of any site is, by default, accessible. (The [Directory “/Library/WebServer/Documents”] block’s directives are explicitly saying that anything within /Library/WebServer/Documents is accessible. This doesn’t change what is already allowed).

However, in Apache2 Apple’s httpd.conf has this:

[Directory /]
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
[/Directory]

[Directory “/Library/WebServer/Documents”]

Order allow,deny
Allow from all
[/Directory]

The [Directory /] block now explicitly makes everything inaccessible below the root of any site by default. Now the [Directory “/Library/WebServer/Documents”] block’s directives are overriding this to grant access to everything under /Library/WebServer/Documents.

That’s fine if your virtual sites are under /Library/WebServer/Documents but if they’re not you get ‘Forbidden – You don’t have permission to access / on this server’.

The solution is simply to add an Allow from all directive for each virtual site’s DocumentRoot, e.g.

[VirtualHost *:80]
ServerName my.virtual.site
DocumentRoot /some/other/path
[/VirtualHost]

Becomes:

[VirtualHost *:80]
ServerName my.virtual.site
DocumentRoot /some/other/path
[/VirtualHost]

[Directory /some/other/path]
Allow from all
[/Directory]

The Allow from all directive overrides the [Directory /] block’s Deny from all directive because it is processed afterwards and the last one processed wins.