Sunday, December 30, 2007

Apache Config: Dealing with mod_dav and .htaccess files

I've been using WebDAV rather than FTP to push files to my dev server. So far, I've been happy with Apache's mod_dav and I've especially liked not having to setup and secure an FTP server.

The other day, though, I ran into a snag. I was publishing a series of files, and the server kept rejected my attempts to publish a .htaccess file. It was the oddest thing. The permissions looked fine, yet I kept getting the message:

  client denied by server configuration

in my Apache error_log.

I Googled around, and to my shock and dismay, couldn't find anyone else who had quite the problem I had. People had issues with permissions and were getting the above error, but nobody was having a mod_dav + .htaccess problem.

I was going to have to figure this out using some other technique than Googling. Ouch.

I opened up my Apache config file and saw the lines:

 # The following lines prevent .htaccess and .htpasswd files from being
 # viewed by Web clients.
 <Files ~ "^\.ht">
     Order allow,deny
     Deny from all
 </Files>

Aha! I was rejecting all requests to .htaccess files for security reasons, including publishing them. If I commented out the above settings, my WebDAV publishing worked fine. But I didn't feel comfortable with doing that, as allowing folks to get access to a .htaccess file would be a Bad Thing.

But how to control who can and can't access .htaccess files? I Googled around, and again, turned up empty handed. I knew I was going to have to do something I hadn't done in years: read the (Apache) documentation.

After poking around the docs, I learned that Limit and LimitExcept are the directives I needed to use. And more importantly, I finally understood how they work. Here's what I learned: you can take a directive, such as Order or Deny and put it in a Limit tag. Doing so, limits (well, duh), it's effect. What I hadn't realized was that the contents of a Limit tag are always valid directives on their own.

So, using my new found knowledge, I came up with:

  <Files ~ "^\.ht">
      <Limit GET POST HEAD>
          Order allow,deny
          Deny from all
      </Limit>
      <LimitExcept GET POST HEAD>
          Order allow,deny
          Allow from all
      </LimitExcept>
   </Files>

In English this says: for GET, POST and HEAD requests, reject access to .htaccess files. For other types of requests, allow it.

I'm not sure this is the most compact way to configure this (or even the most secure), but for my purposes, it'll work.

And more importantly, I finally understand one more piece of the configuration soup that is Apache.

No comments:

Post a Comment