1.7. Creating and Accessing Directories Outside the Web Site Root Directory

Problem

You need to place some files out of the reach of HTTP requests.

Solution

Put your web pages in a directory one level below your login's home directory and create and use directories at the same level as the "web root" to hide private files.

Discussion

I'm always a little annoyed when I FTP or Telnet into a new client's web server for the first time and find that the home directory for the hosting account and the root directory for the web site are one and the same. Such setups are typical of basic hosting accounts and likely keep tech support calls to a minimum by eliminating the need for novice and do-it-yourself web designers to remember file paths on the web server when uploading their web pages. Just FTP into your web server and the site files are right there in front of you.

In these bare-bones web site setups, any file that gets uploaded to the hosting account home directory, or that is created by an automated process on the web site, can potentially be viewed and downloaded over the web. Sensitive or restricted data can include files containing your weblog, email list, or credit card merchant account passwords, database login information or backups, downloadable files that are only made available to authorized site visitors, auto-generated order logs containing confidential information about your online customers, or future versions of important pages on your site to be published at a later date.

Restricted file permissions and password-protected directories are among the other popular methods of keeping private files out of reach of browser requests. But keeping files in a directory that's not even part of your web site (password protected or not) makes worrying about unauthorized web access unnecessary.

First, you'll need to relocate your web site's root directory with a few Apache rewrite rules placed in an .htaccess file, a technique first encountered in Recipe 1.6. You can start using this technique with either a new or existing web site. The changes will be immediate and transparent to your visitors.

Create a directory at the top level of your hosting account home directory—in other words, at the same level as your current home page HTML file. Call the directory something obvious, such as www, web, or htdocs. I'm going to use htdocs for the example below. Now create or modify the .htaccess file in your home directory. Copy into it the following rules for redirecting requests to your domain name to files in the htdocs directory:

	RewriteEngine on

	RewriteCond $1 !^htdocs/
	RewriteRule (.*) / htdocs /$1 [L]

	RewriteCond %{THE_REQUEST} ^[A-Z]+\ / htdocs /
	RewriteRule .* - [F]

The first line ensures that the Apache rewrite engine is on. Lines two and three invisibly redirect browser requests to files in the htdocs directory, but keep the rule from looping indefinitely. Because the rules in the .htaccess file apply to the directory the file is in as well as all the directories below it—including our new htdocs directory—line 3 prevents Apache from appending an infinite number of htdocs to the browser request. Lines 4 and 5 prevent direct requests for files in the htdocs directory.

Copy all your web site files and directories into the htdocs directory, delete the original web site files and directories at the top level of your user account, and you're done. Now you can create other new directories at the same level as htdocs, such as includes, backups, and downloads. None of these new directories will be web accessible.

You can still use standard server-side include tags, introduced in Recipe 1.4, to reference files in the new "super" includes directory, like this:

	<!--#include virtual="/includes/ssi_file.inc" -->

You can also add includes to your web pages that are saved in an includes directory, within your new htdocs directory, like this:

	<!--#include virtual="/htdocs/includes/ssi_file.inc" -->

If your web site uses the popular server-side scripting language PHP, you can configure your scripts to read or write files to directories outside the htdocs directory. Apache's includes functionality begins looking for files at the DocumentRoot specified in its configuration file, which, despite our rewrite rule, is the home directory in our example. PHP, on the other hand, can roam the entire file system of the server, which can make tracking down the exact path to the file you want to include a bit of a mind bender.

Fortunately, you can usually specify a base include path for PHP in your .htaccess file. Open the .htaccess file that you put the rewrite rules into earlier and add the full server path to your home directory.

Tip

If you don't know the full server path to your home directory, use the pwd utility at a command line to your web server to find out.

The line in your .htaccess file should look like this:

	php_value include_path .:/path/to/your/hosting/account/home/directory/

An include statement in one of your PHP scripts that refers to a file above your new htdocs directory would look like this:

<? include ("includes/ssi_file.inc "); ?>

Get Web Site Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.