My most used htaccess settings

Sunday, November 07, 2010 | En Español

The file .htaccess allows us to change some of the settings of a server for a particular directory and it's subdirectories. While it is preferable to make this type of configurations in the server configuration file itself by the use of a <Directory> section, sometimes we simply don't have access to this configuration file, specially when we have a shared hosting account. Most shared hosting providers allows us to make changes to the behavior of the server only in this way.

The .htaccess file is a simple text file that we name like this, note the dot at the beginning of the file name for this is important. We can edit this file in our favorite text editor, and then upload it to our server, placing it in the folder where we want to alter the default behavior.

Some of the things that we can do with the .htaccess file are password protect a folder, create redirections, adjust php settings, control the caching of files, control how extensions are treated by the server (we can make an HTML file be run through the php module instead of just serve it), and in general alter how files are served to the visitors.

This section is likely to be updated in the future with new functionality, however, I will try to cover the most common uses that I have for this file.

Topics
Disabling the file listing in directories without an index file
Creating a redirection or changing the response status of missing files
Creating custom error response pages
Setting the cache expiration time of different types of files
Compressing the files before serve them to the browser
Password protecting a folder
Treating HTML files as PHP files
Changing default PHP settings

Disabling the file listing in directories without an index file

By default, when we access a subfolder in a website that does not have an index file (whether it's .html, .htm, .php), the server will show us an list of the content in the folder, the typical "Index of" followed by all of the files and subdirectories in the directory we are accessing. This setting is particularly dangerous, as it may expose the inner structure of our website and/or provide access to files and information that we would rather not show publicly but that for some reason we put in there.

In order to disable this setting, we can create an .htaccess file in the root folder of the website, and add to it the line:

Options -Indexes

Creating a redirection or changing the response status of missing files

When we request a file from a server, and this file is not found, by default the server returns a 404 status code, a status that indicates the browser (and us, as the browser will present us this status code) that said file is not available there. But it is only a generic message, it indicates nothing but the fact that right at that very moment the file is not accessible. However sometimes we can indicate the browser why the file is not currently there so the browser can act properly. My three most used cases are:

The file has been moved permanently

The status 301 indicates the browser that the file has been permanently moved to a different location. This is a good way to implement a redirection with .htaccess, as browsers with link editing capabilities will automatically update all references to the file to the new address. And this response is cacheable, which means that a browser won't keep trying to access that address and will instead request the new address of the file. Just add to your .htaccess the following line, indicating the file that was moved, which may be any type of file, and the new location of the file.

Redirect 301 /path/from/htaccess/file.html http://www.domain.tld/path/file.html

The file has been moved temporally

The status 307 indicates the browser that the file was moved, but that this move is only temporal, the browser will follow the new address as it does when it receives a 301 status, but it will not change any links to the file, nor will it create a cache with this new address (unless it's indicated by a Cache-Control or an expiration header field), the browser will continue requesting the original direction every time.

Redirect 307 /path/from/htaccess/file.html http://www.domain.tld/path/file.html

The file is gone

The status 410 indicates the browser that the file being requested has been permanently removed from the server. Unlike the 404 status, which only indicates that the file is not there, this status code indicates that the file is not going to be there anymore.

Redirect 410 /path/from/htaccess/file.html

Creating custom error response pages

Instead of send back to the browser a status code, so that it can present us with it's own error page, we can create custom error pages, e.g. for the errors 401 (Unauthorized) and 404 (not found). All we need to do it's modify our .htaccess file, adding the following lines:

ErrorDocument 401 /path/to/401.html
ErrorDocument 404 /path/to/404.html

Setting the cache expiration time of different types of files

This setting will indicate the browser how long it should keep the cache of the files so it won't query the server for this files every time that they are needed, this is what I refer to when I speak of Cache-Control. What happens here is that the server will send a "Expires" header accompanying the files that it serves.

We can define the default expiration time of files with the directive ExpiresDefault followed by a base and a time, or we can specify the expiration time of specific types of files with ExpiresByType, followed by a file type, a base and a time.

The base can be either the access time or the modification time, where access starts counting the time since the browser requested the file, and modification starts counting the time from the last time that this file was modified. Note that if you use a modification based expiration, the Expires header will not be added to content that does not come from a file in the disk, as in the case of an on-the-fly generated image, this is of course because a non existent file can not possibly have a modification date.

And the time is used in conjunction with the base, by adding a plus and a time, this time can be given in seconds, minutes, hours, days, weeks, months or years, and it can be expressed in singular if we only use one unit, we can specify it as "1 minute" or as "10 minutes".

In this example I am going to set a default expiration time for all files of one day, by using the ExpiresDefault directive, and then specify different expiration times for common types of files using ExpiresByType.

<ifModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 day"
    ExpiresByType image/png "access plus 30 days"
    ExpiresByType image/jpeg "access plus 4 weeks"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 year"
    ExpiresByType application/javascript "modification plus 2 weeks"
    ExpiresByType text/css "modification plus 14 days"
</ifModule>

Compressing the files before serve them to the browser

About every modern browser have the ability of request, accept and process the information received from the server in a compressed way, in order to reduce the loading time of the web site when it is being served.

To enable the compression of files, in case the server is not configured to do this by default, we need to add to our .htaccess file the line:

AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/x-javascript application/rss+xml application/atom_xml text/javascript

We don't add here images and other type of content, because our images and other elements should be already using some sort of compression. The server doesn't start to serve every file compressed, only does it when the browser tell it that it can receive compressed information.

Password protecting a folder

In order to protect the contents of a folder we need to create a file containing a list of valid usernames and passwords, and add some lines to our .htaccess file. The username and the password will be send in plain text to the server, so it is still vulnerable to man-in-the-middle attacks, unless we use SSL (highly recommended).

We start by creating a file called .htpasswd, change the permissions of the file to 644.

touch .htpasswd
chmod 644 .htpasswd

Once this is done, we need to fill the file with the usernames and the (preferably and highly recommended to be encrypted) passwords. If you are using Linux or another Unix based operating system and count with the program htpasswd this is easy to do, or even better, if you can log in via SSH to your server you can use htpasswd to manage the usernames and passwords in the file. If not, there are multiple online utilities that will allow you to generate the encrypted passwords for use in your .htpasswd file (I don't trust any of them, but then I am a paranoid person). Here is one of such sites http://www.htaccesstools.com/htpasswd-generator/

To generate the password and store it along with the username in the file, we can use:

htpasswd [passwd file] [user]

e.g.

htpasswd .htpasswd juan

This will prompt you for the password, and then it will encrypt it and store it in the .htpasswd file.

By default, if apache is installed in any system but Windows, Netware and TPF (Transaction Process Facility, an IBM mainframe) it will use the function crypt() to encrypt the password. Using this command we can create as many users as we want, as well as change the password of any existent user in the file.

Optionally you can use the parameter -n to obtain the results of the command:

htpasswd -n juan

Again, this will prompt you for the password, and it will return something like this:

juan:n94xSo6uSwhCY

You can open the file .htpasswd in your favorite text editor and paste the information, one per line if you give access to multiple users.

Other ways of encrypt the password may be with MD5 by using the command -m, this is the default in Windows, Netware and TPF. Or you can use SHA instead with the parameter -s. And the parameter -d makes the command use the crypt function but this is already the default behavior in most systems.

Some additional parameters of htpasswd are -c which will create the file if this doesn't already exist, or rewrite it and truncate it if it already exists, leaving only the new user on it. The parameter -D will delete a user from the .htpasswd file if this exist.

And finally, in case we want to use this command in conjunction with other commands, we can use the parameter -b which allow us to specify the password in the command line. For obvious reasons, this is not a very secure way to do this, specially if the command is logged in the history (we can use a space before the command to prevent it from being recorded in our history, but still, this is not a recommended way to do it).

htpasswd .htpasswd juan randompassword

Once we are done creating users that will be able to access the directory and it's subdirectories, we need to add the following lines to our .htaccess file located in the folder that we want to protect:

AuthName "Please authenticate in order to access the contents of this folder"
AuthType Basic
AuthUserFile /full/path/to/.htpasswd
Require valid-user

Where AuthName is the text that appears in the prompt requesting the username and the password. AuthType is the type of authentication required, in this case we want a simple dialog box prompting us for a username and a password, so we use Basic. AuthUserFile is the file where the list of usernames and passwords is located, in this case is named .htpasswd and is located in the same folder as our .htaccess file. And finally Require valid-user makes this folder only accessible to valid users, as defined in the .htpasswd file.

Treating HTML files as PHP files

To treat files with an html extension (or any other extension) as PHP files, i.e. to make the server parse the html files through the PHP module instead of just serving them directly to the browser, we need to add the following lines to our .htaccess file:

AddType application/x-httpd-php .htm .html

Update: PHP does not always run as a module, some times it runs as CGI (Common Gateway Interface). To achieve the same thing when PHP is used as CGI use the following code:

AddHandler application/x-httpd-php .html .htm

In some servers running PHP as CGI the following code would also work:

AddHandler php5-cgi .html .htm

Changing PHP settings

If we don't have access to the php.ini file, some hosting providers allows to change some of it's default settings by modifying the .htaccess file, e.g. if I am generating thumbnails of uploaded images as I described in some of my previous posts (scaled thumbnails, cropped and scaled thumbnails), the default memory limit of PHP in some hosting providers is as low as 2 MB, this is just not enough to process images with the sizes that are used nowadays, so I change this limit to something bigger, something like 16 MB should be good enough for most images. But this is not the only useful setting that we can change from the default php.ini configuration, I will probably make a post on this later. The default memory limit in for PHP scripts has been increasing, the default before PHP 5.2.0 was 8 MB, after PHP 5.2.0 it was increased to 16 MB, currently it is 128 MB. Also, to remove the memory limit, this can be set to -1 .

To change a PHP default setting in our .htaccess file, the option AllowOverride Options (or AllowOverride all) must be on in the server. If it is on, we just need to add the following line to our .htaccess file:

php_value memory_limit 16M

This is, php_value, followed by the setting name, followed by the new value.

Categories: Apache, FOSS, PHP