Dugan Chen's Homepage

Various Things

Bootstrap Directory Index Skins for Apache and Ngnix

This is how you can get nicer directory indexes in Apache and Nginx.

First, have you ever used h5ai? I have. It’s great. But now, I want something lighter. I want a solution that does not defer to a CGI, an application server, or equivalent. I want something that uses only the web server itself. This solution should render valid HTML5, formatted using something nice, such as the Twitter Bootstrap.

Here are solutions for Apache and Nginx.

In both cases, I assume that you have “user directories” turned on, using the default settings. For example, ~dugan/public_html/blah.jpg will be served as http://SERVER/~dugan/blah.jpg.


With Apache, it’s simple. You create two HTML files: one for everything above the listing and one for everything below it.

You have the following HTML file, header.html:

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<title>Listing directory</title>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">

And you have the following HTML file, footer.html:

(function () {
    'use strict';

    window.addEventListener('DOMContentLoaded', function () {
        var i,
            items = document.querySelectorAll('li');


        for (i = 0; i < items.length; i += 1) {


And then, in the root of the directory that you’re indexing, you have the following .htaccess file:

HeaderName /path/to/header.html
ReadmeName /path/to/footer.html
IndexOptions +SuppressHTMLPreamble -FancyIndexing

Global Installation

For example, if header.html is at http://SERVER/header.html and footer.html is at http://SERVER/footer.html, then the .htaccess will be:

HeaderName /header.html
ReadmeName /footer.html
IndexOptions +SuppressHTMLPreamble -FancyIndexing

Per User Installation

And if header.html is at http://SERVER/~dugan/header.html and footer.html is at http://SERVER/~dugan/footer.html, then .htaccess, which can be at ~dugan/public_html/.htaccess, will be:

HeaderName /~dugan/header.html
ReadmeName /~dugan/footer.html
IndexOptions +SuppressHTMLPreamble -FancyIndexing


Nginx, unfortunately, is not as easy. Its directory listings aren’t configurable at all unless you use NgxFancyIndex, and even then I ended up forking it in order to get what I wanted.

I followed the instructions in its HACKING.rst to get the HTML that I wanted.

I also patched NgxFancyIndex to not truncate filenames at 50 characters. I changed it to a more reasonable 255 characters. The instructions to do so apply to NgxFancyIndex. In the source file ngx_http_fancyindex_module.c, I changed the definitions of NGX_HTTP_FANCYINDEX_PREALLOCATE and NGX_HTTP_FANCYINDEX_NAME_LEN from 50 to 255.

Well, I’ve done all that. Just clone my fork:

git clone https://github.com/duganchen/ngx-fancyindex.git

And build nginx against it:

./configure --add-module=/path/to/ngx-fancyindex

And then, in nginx.conf, set your user directories to use fancy indexing:

location ~ ^/~(.+?)(/.*)?$ {
    fancyindex on;
    alias /home/$1/public_html$2;
    index index.html index.htm;

UPDATE: Please use my ngx-responsiveindex project instead.