Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'd like to configure httpd.conf to deny files that match either of the following:

  1. A directory that starts with . or _
  2. A file that starts with . or _, but does not match __\w+__\.\w+

For example:

/_private/anything       ->  deny (rule 1)
/_private/__init__.py    ->  deny (rule 1)
/_private/_private.txt   ->  deny (rule 1+2)

/public/_private.txt     ->  deny (rule 2)
/public/__private.txt    ->  deny (rule 2)
/public/__public__.txt   ->  allow

I've been working with <Directory ~ "..."> and <Files ~ "..."> as well as RewriteRule, but haven't been able to get it working just right.

Suggestions much appreciated!


Update: in response to CK:

<Directory "/var/www/html">
    Order allow,deny
    Allow from all

Update 2: Does anyone know why this directive is matching and denying a url like /_test.php, when it is clearly not a "directory" ? (I removed ALL <Files> sections except the .htaccess one.)

<Directory ~ "/[._]">
    Order allow,deny
    Deny from all
share|improve this question
What is your current config? What permissions are on <Directory />? –  CK. Aug 3 '09 at 23:30

3 Answers 3

It sounds like you are looking for "DirectoryMatch and FileMatch.

From the apache httpd website. http://httpd.apache.org/docs/2.0/mod/core.html#directorymatch

< DirectoryMatch> and < /DirectoryMatch> are used to enclose a group of directives which will apply only to the named directory and sub-directories of that directory, the same as . However, it takes as an argument a regular expression.


The < FilesMatch> directive limits the scope of the enclosed directives by filename, just as the < Files> directive does. However, it accepts a regular expression.

share|improve this answer
As I pointed out in my post, I am using <Directory ~ "..."> which, according to the apache docs, are exactly the same as <DirectoryMatch ...>. –  gahooa Aug 4 '09 at 2:43
The way you were describing the issue looked as if you wanted regex matching instead of directives that only understand shell type wildcard globing. –  Rik Schneider Aug 6 '09 at 4:15

as with most things like this, the order of rules is crucial.

the best rule of thumb, IMO, is to put the special-case exceptions first and then the general case rule, like so:

  1. allow files that match (^|/)__\w+__.\w+$
  2. deny files or directories that match (^|/)[._]

if the order were reversed from the above, then the file-match exception would never even be reached, so wouldn't have any effect.

BTW, why have such silly rules? why not just put public files in one directory and private files in another? why have private files like '_private.txt' in a directory called /public? why make your public file and directory names so annoyingly similar to your private names? it would make more sense to do things in a more convenient, sensible fashion - sometimes the best answer is DDTT - "Don't Do That, Then".

share|improve this answer
Hi Craig. I believe your suggested rule order would allow /_hidden/__init__.php -- is that true? Regarding the BTW, I appreciate you taking the time to write that, but can assure you that there is a bigger picture that I did not take up room in the post to explain. 99% of our non-http accessible files are completely outside the DocumentRoot, but there are some specific exception (with very good cause) that live inside the document root. Either they are directory level PHP or Python runtime configuration files. Calling this silly would be the same as calling apache's .htaccess silly. –  gahooa Aug 4 '09 at 2:50
re: /_hidden_/__init__.php - yes, it would. that's one of the problems with having such similar patterns for your private and public files. you've got three basic options: 1. construct the regex to exclude each private directory, 2. construct it to include each public directory. both of these are potentially never-ending, so the best is option 3. work out some other file/directory naming scheme so that you can have a simple regex that matches all files you want to block while not matching any you want to allow. that's why i called it silly...this is a DDTT problem. –  cas Aug 4 '09 at 3:01
also, add another rule (before the first one) that blocks directories matching (^|/)[._].*/ –  cas Aug 4 '09 at 3:05

EDIT: from comment reply original post wasn't quite right - below is new Rewrite rule set:

RewriteRule /\..+ - [F]
RewriteCond %{REQUEST_URI} ^/[^_]+/__\w+__\.\w+$ [NC]
RewriteRule ^ - [S=1]
RewriteRule /_.+ - [F]

Order is important here: - forbid anything starting with period (.) first - its a "global" rule with no special case. - the special case of __\w+__.\w+ must be allowed through next S=1 skips the next rule being - forbid anything starting with underscore (_)

share|improve this answer
Hey, that's really close. But it's running into the same problem I was having... /_sam/__foo__.txt is allowed. My wheels are turning, however, and I think this is the right approach. Maybe I should wait until morning :) –  gahooa Aug 4 '09 at 2:58
Edited post with working version for ya –  DisabledLeopard Aug 4 '09 at 3:57

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.