mail us  |  mail this page

contact us
training  | 
tech stuff  | 

Apache Configuration

This section deals with initial configuration of Apache to support SSI on Linux (RedHat 6.2 and 7.1 to be precise other distributions may vary), the use of the XBitHack directive, detecting browser types using the 'BrowserMatchNoCase' directive and including and conditionally generating pages using SSI.

Configure Apache for Server Side Includes (SSI)

You need to edit your Apache configuration (httpd.conf) file (for RedHat distributions this is in /etc/httpd/conf/httpd.conf). Someone has done a great job with the standard httpd.conf file, in general for non-exotic stuff all you have to do is find the appropriate lines and uncomment them.

Note: As a general rule we always comment changes to all config files with the date, person's initials and brief reason for the change.

Make the following changes to httpd.conf:

General section:

The first change defines the type of files that contain SSI and how they are recognised, 'server-parsed' is the shortform and tells Apache to parse for SSIs any file with a suffix of .shtml.

# To use server-parsed HTML files (SSI) add or uncomment
# the following lines
AddType text/html .shtml
AddHandler server-parsed .shtml

..and here also..(this makes sure the SSI module (mod_include) is present and used at run time)

# To use server-parsed HTML files (SSI) add or uncomment
# the following lines
# They are in separate locations in the file but shown together 
# for convenience
LoadModule includes_module    modules/
AddModule mod_include.c

Finally you have to tell Apache to enable the Includes feature using the following directive:

Options +Includes

You can place this directive in the root directory section in which case it will enable SSI for all sub-directories (typically the whole server) or you can place it in a <VirtualHost> section with a <Directory> entry. We chose to enable SSIs for the whole server so we placed the directive in our root directory section as follows:

# DocumentRoot: All our web servers operate as sub-directories of this 
# root

DocumentRoot /var/www

# all permissions defined here operate on all web servers unless
# we define more restrictive permissions in other <directory> sections
# inside or outside <virtualhost> sections

<Directory "/var/www">
# This enables a number of features as well as 'Includes' (SSIs)
# on all sub-directories (server-wide)
    Options Indexes Includes FollowSymLinks

# This controls which options the .htaccess files in directories can
# override.
    AllowOverride All
# Controls who can get stuff from this server.
    Order allow,deny
    Allow from all

When using SSI in theory you have to make every file containing SSI directives have the suffix .shtml but those Apache folks are smart and 'cos mugs like you and me haven't discovered scripting languages (to rename every file in a directory) they allow you to use the XBitHack directive. The 'XBitHack On' directive tells Apache to look at every file with execute permission and parse it for SSIs. On a busy server this can be quite a load.

However as with most Apache directives it depends where you put the directive. If you place it in the General section the rule applies to all servers and virtual servers hosted. If you place the directive in a <VirtualHost> section then it only applies to that virtual host. For performance reasons we chose to place the directive in a virtual host section as follows:

<VirtualHost xxx.xx.xx.xx>
    DocumentRoot /var/www/smokeyjoe
    XBitHack On
    ErrorLog logs/smokejoe-error_log
    CustomLog logs/smokeyjoe-access_log common

NOTE: to set the execute permission for a single file use:

chmod +x
To change permissions for a whole directory use:
chmod +x -R /directory/name

Now you are almost ready for bear ...but don't restart your Apache server yet....

Configure Apache Browser Detection

Apache really is a very good piece of software with more features than you can shake a stick at. You can get Apache to set some variables that you can then use to generate your SSI code conditionally.

To perform this magic you use the Apache directive <BrowserMatchNoCase> or <BrowserMatch> which will apply a regular expression check (for a survival guide to regular expressions read the grep man page under unix or go here) to the environmental variable HTTP_USER_AGENT which is supplied by every browser (a full list of Apache environmental variables is here).

By judicious checking you can find out the browser, its version, its platform even and anything else that may take your fancy. Again you can add the lines to the 'General section' or a <VirtualHost> section. We have never seen a comprehensive list of Browser ID (or user-agent) strings so we started one here. In our case we added them to the 'General Section' to provide a single consistent set of variables to all the <VirtualHosts> on our server (and hopefully reduce load by everyone doing the same thing over and over again. We modified the 'General section' of httpd.conf as follows:

BrowserMatchNoCase Mozilla/[4-6] isJS
BrowserMatchNoCase MSIE isIE
BrowserMatchNoCase Gecko isW3C
BrowserMatchNoCase MSIE.((5\.[5-9])|([6-9])) isW3C
BrowserMatchNoCase W3C_ isW3C

For a full explanation of these tests and an overview of regular expressions go here.

Now you can restart your Apache server 'cos you are ready for some action.

Server Side Browser Specific Generation

To generate code conditionally you can now place SSI statements in any file with a .shtml, .htm or .html (or even .php) file. SSI statements look like HTML comments and take the general format (full SSI list)

<!--#element attribute=value attribute=value ... -->

There MUST NOT be a space between the '#element' and the second opening '-' and there MUST BE a space between the last character of the last 'attribute=value' pair and the first closing '-'.

We make extensive use of only two elements, 'include' and 'conditional expressions' but have included an SSI 'blow-by-blow' explanation.

The 'include' element

The following shows a sample of one of our standard template .htm files, we just load it and 'save as' the target file name and then add the content:

<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html">
<meta name="GENERATOR" content="company name">
<meta name="keywords" content="blah blah, blah">
<title>Level 1 template</title>
<!-- conditionally generated style sheet -->
<!--#include virtual="/templates/styles.shtml" -->
<!-- conditionally generated javascript code -->
<!--#include virtual="/scripts/js.shtml" -->
<!--#include virtual="/templates/level_1.html" -->
<!-- begin body div -->
<div class="l-c">
<!--  insert body text here -->

	<!-- end body (l-c) div -->
<!--#config timefmt="%B %d %Y" -->
<!--#set var=\"real_date\" value=\"$LAST_MODIFIED\" -->
<!--#include virtual="/templates/footer.shtml" -->

We always include the css style sheet, the javascript code, the page header and the page footer from standard files. You can use the <LINK> tag for the style sheet and the 'src=file.js' in the <SCRIPT> section but we chose to minimise the number of web server accesses at the cost of exposing all our javascript code.

The #config and #set lines before the #include for the "footer.shtml" file is our way ensuring that the LAST_MODIFIED date is for this file not the footer file. We format the date (month day, year), save the current LAST_MODIFIED to the variable 'real_date' and then use "#echo var="real_date" in the footer file (go here for more info on SSI directives including this technique).

Nesting SSI Expressions

The more observant among you may have noticed that some include files have an .shtml suffix and others not. If you want to use SSI expressions in an 'included' file then that file MUST have a .shtml suffix (even if you are using the XBitHack). We did not find this out until very late and had to modify 'include' lines in over 100 html files (well actually we found a fantastic 10 line PHP script to do it for us).

SSI 'conditional expressions'

The following code snippet shows how we generate browser conditional css style data from an styles.shtml file (remember we are nesting SSI directives so must use a .shtml file suffix):

<!-- Different browser values here -->
<!--#if expr="${isW3C} && !${isIE}" -->
/*  W3C compliant browsers - currently just Gecko */
.n-l-s {font:bold 9pt Verdana,sans-serif;
.popup {font:bold small Verdana,sans-serif;
<!--#elif expr="${isIE}" -->
/*  Explorer and other DHTML browsers */
.n-l-s {font-family:Verdana,sans-serif;
.popup {font-family:Verdana,sans-serif;font-size:small;
<!--#else -->
/* NS4.x CSS and display options here */
.n-l-s {font-family:Verdana,sans-serif;
       font-size:8pt;font-weight:bold; text-decoration:none}
.popup {position:relative;font-family:Verdana,sans-serif;
#lnav0 {position:relative;top:0;left:0;}
<!--#endif -->

The code is trivial but will get a tad more complex as we add additional capability (we now support the W3C'ish DOM (Gecko) IE 5.5+ and NS4.x). In the above simple example we test the variable 'isIE' (which Apache has kindly set for us above) and directly branch to the #else or #endif statements.

Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.

Copyright © 1994 - 2017 ZyTrax, Inc.
All rights reserved. Legal and Privacy
site by zytrax
Hosted by
web-master at zytrax
Page modified: May 15 2014.

Tech Stuff

If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox


Share Page

share page via facebook tweet this page submit page to stumbleupon submit page to

Page Features

Page comment feature Send to a friend feature print this page Decrease font size Increase font size

HTML Stuff

W3C HTML 4.01
HTML5 Reference
W3C Page Validator

CSS Stuff

W3C CSS2.1

DOM Stuff

W3C DOM Events
Gecko DOM

Web Style Guide

Jolly Useful

Peter-Paul Koch
A List Apart
Eric Meyer on CSS
DOCTYPE definitions

Our Stuff

Our DOM Pages
DOM User Guide
DOM Explorer
DOM Navigation
CSS Techniques
CSS Short Cuts
CSS overview
Oh Really!




CSS Technology SPF Record Conformant Domain