modified nginx index list

I’ve always been envious of the directory listing that Caddy has for serving files. Nginx also has the capability to list directories and files.

This is extremely useful to serve a directory out quickly over LAN or even where it is required to serve a directory listing instead of a web page.

However, the default Nginx styling leaves a lot to be desired!

The way to serve a directory out in Nginx is by the autoindex directive.

The following configuration has the autoindex directive as well as the index directive against which a random string like nothing_will_match has been set so that Nginx doesn’t show the index.html file by default.

http {
  server {
    server_name    _;
    autoindex      on;
    location / {
      root        /home/abhijit/myapp;
      index       nothing_will_match;
    }
  }
}

For a directory with a Javascript application, the browser shows this.

nginx default listing

This is seriously ugly!

To change it and make it look like the image on top of this post, a few of the other nginx directives are used.

The final Nginx configuration looks like this.

(Thanks to Nick Bettison for pointing me in the right direction.)

http {
  server {
    server_name    _;
    autoindex      on;

    location = '/favicon.ico' {
      alias /etc/nginx/theme/favicon/favicon.ico;
      access_log		off;
      log_not_found	off;
    }

    location /theme/  {
      root   /etc/nginx;
    }

    autoindex              on;
    autoindex_exact_size   off;
    autoindex_localtime    on;
    add_before_body        "/theme/nginx-before.html";
    add_after_body         "/theme/nginx-after.html";

    location / {
      root        /home/abhijit/myapp;
      index       nothing_will_match;
    }
  }
}

The theme folder could be placed anywhere. I choose to keep it in my nginx folder itself. It consists of all the necessary files.

The main files in this folder are nginx-before.html and nginx-after.html.

nginx-before.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Directory Listing</title>
    <meta charset="utf-8" />

    <!-- Styles -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/light.min.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

    <link rel="stylesheet" href="/theme/css/link-icons.css">
    <link rel="stylesheet" href="/theme/css/style.css">
</head>

<body>
  <div id="title">
      <span>Directory Listing</span>
      <span class="stats" id='file-stats'></span>
      <span class="stats" id='dir-stats'></span>
  </div>

  <div id='listing'>
      <div>

Here, I’m using the amazing Water.css for the basic styling. And the 4.7.0 version of Font-Awesome.

Beyond that, I’m also using the CSS link icons from Greg Schoppe.

nginx-after.html

    </div>
  </div>
</body>
    <!-- Script -->
    <script type="text/javascript">
      var pathElement = document.querySelector('#listing h1');
      pathElement.className = 'listing';

      var pathName = pathElement.innerHTML;
      pathName = pathName.replace('Index of ', '');
      pathElement.innerHTML = pathName;

      var fileCount = 0
        ,dirCount = 0
        ,dirStatElem = document.getElementById('dir-stats')
        ,fileStatElem = document.getElementById('file-stats')
      ;

      var allLinks = document.getElementsByTagName('a');
      for (let item of allLinks){
        if (item.innerHTML != "../"){
          if (item.innerHTML.endsWith('/')){
            dirCount += 1;
          }
          else {
            fileCount += 1;
          }
        }
        item.className = "link-icon";
      }

      var parentFolderElement = document.querySelector("a[href='../']");
      parentFolderElement.className = "folderup";
      parentFolderElement.innerHTML = "&#8682; Up";

      if (dirCount == 1){
        dirStatElem.innerHTML = dirCount + " directory";
      }
      else {
        dirStatElem.innerHTML = dirCount + " directories";
      }

      if (fileCount == 1){
        fileStatElem.innerHTML = fileCount + " file";
      }
      else {
        fileStatElem.innerHTML = fileCount + " files";
      }

    </script>
</html>

Here, I’m using some simple Javascript to add CSS classes and to change the folder up icon and to count the number of files and directories.

body {
  max-width: 90%;
}

#title {
  font-size: 1.1em;
  margin: 5px 0;
}

#title .stats {
  font-size: 0.8em;
  float: right;
  margin: 0 10px;
}

#listing {
  font-size: 1.1em;
}

#listing h1 {
  font-size: 1.1em;
}

.folderup {
  color: #FFCA28;
  font-size: 1.4em;
  font-weight: bold;
}

Had to do some minor modifications to Greg Schoppe’s stylesheet.

/* a[href$="/"].link-icon:before, */
/* a[href$=".html"].link-icon:before, */

a[href$="/"].link-icon:before,
a.link-icon.link-folder[href]:before {
  content: "\f07b"; /*Folder*/
}
a[href$=".html"].link-icon:before,
a.link-icon.link-html5[href]:before {
	content: "\f13b"; /*HTML5*/
}

Now Nginx looks much more presentable!

Switching to the dark theme looks pretty good as well!

nginx modified dark listing