Simplifying your site with Server Side Includes
Server Side Includes (SSIs) can save you time and make your website easier to maintain.
Most websites have a handful of elements that are common to all or most pages, such as headers, footers, and menus. Hard-coding these sections into each page means that if you ever make any changes, you have to edit every single page, which is very tedious and not a good use of your time. Server Side Includes (SSIs) are an easy way of writing HTML snippets once only and then including them in your pages with a single reference.
Writing the Include File
Before setting up the web server to handle SSIs, I'll start by defining some SSI content. Listing 1 shows a basic footer include file, containing just the footer information I want at the bottom of each page. (The styling is all in the CSS, which I'm not showing here – this is just the HTML logic. It is always good practice to separate content logic from presentation and styling.)
Basic Footer Include File footer.html
01 <div id="footer"> 02 <p><a href="mailto:firstname.lastname@example.org">website contact</a></p> 03 <p><a href="http://www.mysite.com">return to homepage</a></p> 04 </div>
As shown in Listing 2, I find it best to create a directory for includes in the web server's root directory. This approach helps you keep track of the include files and avoid confusing them with your regular HTML files. An organized directory is particularly important for files that apply to the whole site; if you have includes that are specific to a particular subdirectory, you might want to keep them with that subdirectory.
Setting Up an Includes Directory
01 mkdir /var/www/includes 02 chown www-data /var/www/includes 03 mv footer.html /var/www/includes
The web server doesn't serve the include file directly; instead, you use it by including a reference to it in a regular HTML file. The contents of the include file will effectively be dumped straight into the HTML file in place of the reference (without any actual change to the file on the disk; the alterations are made on the fly as the page is served up).
Now I need to set up a test HTML file that includes this footer file, as in Listing 3. Note the .shtml ending – I'll discuss this ending in the next section, and don't try viewing this file in your browser yet! It won't work until the web server is set up correctly. The syntax used for the reference here (the single line starting <!--#include) is the standard syntax for an SSI reference.
01 <html> 02 <head> 03 <title>Testing SSIs</title> 04 </head> 05 <body> 06 <h1>Testing</h1> 07 <p>Still testing.</p> 08 <!--#include virtual="/includes/footer.html" --> 09 </body> 10 </html>
Setting Up Your Web Server
At this point, the files are set up, but the server can't serve them correctly – if you look at the test.shtml file, the footer won't be in it. To get it running correctly, you need to set up your web server (here, I'm using Apache, but other servers can also deal with SSIs).
The first step is to enable the include module, which lets Apache deal with SSIs. In a Debian/Ubuntu system, use a2enmod include; otherwise, add the line in Listing 4 to your /etc/apache/apache2.conf file (you might need to edit the path to the module if your configuration is non-standard).
Add This Line to apache2.conf
01 LoadModule include_module /usr/lib/apache2/modules/mod_include.so
Apache now can parse SSIs, but you need to tell it to permit the parsing of SSIs. To do this, add an Options +Includes directive within the directory in which you want SSIs to work. In Listing 5, this is the main directory, /var/www/.
Allowing Apache to Parse SSIs
01 <Directory /var/www/> 02 Options +Includes 03 </Directory> 04 05 <Directory /var/www/main/> 06 Options FollowSymLinks 07 </Directory> 08 09 <Directory /var/www/secondary/> 10 Options +Indexes 11 </Directory>
Note that if you have specific settings for subdirectories of this directory that do not use the + syntax to set their other options, Apache will override the Includes option. With Apache Options, putting + in front of an option means "add this to any existing or inherited options," whereas leaving off the + means "replace any existing or inherited options with this set of options." (Using a - in front of the Option means "remove this option.")
So in Listing 5, the /var/www/main/ directory will not have Includes set (only FollowSymLinks), whereas /var/www/secondary/ will have both Includes and Indexes set.
Once you've set the Options correctly on your directories, the final step is to tell Apache which files to parse. Unless you're certain that all your files really do have SSIs, you don't want it just to parse every single file because it will slow down the delivery of files that don't have any SSIs included.
One way to tell Apache where to look for files is to treat any that end with .shtml as those to parse for SSIs. To do this, add the two lines shown in Listing 6 within the <Directory> tags set up in Listing 4.
Parsing .shtml Files for SSIs
01 AddType text/html .shtml 02 AddOutputFilter INCLUDES .shtml
Now reload your server (with /etc/init.d/apache2 force-reload) and go look at your test.shtml page with a browser. You should see your first page with SSIs (Figure 1).
The downside to this approach is that you have to rename any existing files in which you want to use SSIs as .shtml files in order for them to be parsed correctly. Alternatively, you can tell your server to rewrite all .html files as .shtml files by enabling the rewrite module (a2enmod rewrite) then adding the lines in Listing 7 within the <Directory> tags.
Enabling the rewrite Module
01 RewriteEngine on 02 RewriteBase / 03 RewriteRule ^(.*)\.html $1.shtml [R=permanent]
However, this approach is tantamount to just telling the server to parse all .html files for includes, which will have performance implications. You could also use find and xargs to change all your .html files to .shtml and then manually change back any that shouldn't be treated in this way.
This directive tells Apache that any file with the execute bit set should be parsed for SSI directives. To check out your test file, change its execute mode with chmod +x test.html. (Then do that to any other files in which you want to use SSI directives.)
Note that you should use either the method shown in Listing 6 or the XbitHack directive – but not both!
Now reload Apache with /etc/init.d/apache2 force-reload, and try loading your test file by pointing your browser at http://www.mysite.com/test.shtml (or test.html if you've used the XBitHack directive).
Further Uses of SSIs
One very useful thing you can do with SSIs is nest them, so an include file can include a reference to another include file. An example of this might be when you want to have a menu with submenus that are included on every page (Figure 2; see Listings 8 and 9).
Main Menu Include File menu.shtml
01 <ul> 02 <li>About Us 03 <!--#include virtual="/includes/aboutmenu.html" --> 04 </li> 05 <li>Documentation</li> 06 <li>Contact Us</li> 07 </ul>
Submenu Include File aboutmenu.html
01 <ul> 02 <li>Location</li> 03 <li>Mission Statement</li> 04 <li>People</li> 05 </ul>
Note that you'll need to set up menu.shtml to be parsed – either, as here, by using a .shtml extension or by using XBitHack and setting the execute bit as described previously.
SSIs also support various other commands and variables. For example, to output today's date, use:
<!--#echo var="DATE_LOCAL" -->
The DATE_LOCAL variable is one of the standard set of variables available to CGI programs, which SSI can also access. (See http://www.georgedillon.com/web/ssivar.shtml for a useful list of variables.) Additionally, you could output the last date modified, as in Listing 10.
Adding the Last Date Modified
01 <html> 02 <head></head> 03 <body> 04 <p>Some text.</p> 05 <p>This page last modified: <!--#echo var="LAST_MODIFIED" --></p> 06 </body> 07 </html>
The default date format is a full date with the time, as shown in Figure 2. You can also set the time/date format before you echo the time. For example, the code shown in Listing 11 would output just the date with the format: Tue 28 Jul, 2009.
Formatting the Date
01 <!--#config timefmt="%a %d %b, %Y" --> 02 <!--#echo var="DATE_LOCAL" -->
Finally, you can use includes to run a CGI program, or any other code, and output the result. For example, the code in Listing 12 produces a directory listing.
Note that Listing 12 is a big security risk! Because you can execute any arbitrary code within that exec block, if you allow SSIs on a page in which users can edit content (a wiki page or a page with comments of some sort turned on), an attacker could do many bad things. To turn this feature off, set the Options directive –
– just to be safe.
A Directory Listing in Your Page
01 <html> 02 <head></head> 03 <body> 04 <p>Other files in this directory: 05 <!--#exec cmd="ls -l" --> 06 </p> 07 </body> 08 </html>
Kernel king admits his tone has alienated volunteers, but says the demands of the process require directness.
New flaw in an old encryption scheme leaves the experts scrambling to disable SSL 3
Lennart Poettering wants to change the way Linux developers talk to each other.
Enterprise giant frees itself from ink and home PCs (and visa versa).
Mozilla’s product think tank sinks silently into history.
TODO group will focus on open source tools in large-scale environments.
New tool will look like GParted but support a wider range of storage technologies.
New public key pinning feature will help prevent man-in-the-middle attacks.
Carnegie Mellon researchers say 3 million pages could fall down the phishing hole in the next year.
The US government rolls new best-practice rules for protecting SSH.