How to rewrite and forward .*/index.html to .*/ with nginx and Apache

Recently, I decided to clean up my index urls. I had .*/index.html files, directory listings at .*/, indirect serving of index.html to .*/, many times with the index being reachable via two urls without forwards. It's good practice to have only one URL for a specific page (and it also makes the GoogleBot happy), so I looked into forwards and redirects with Apache and nginx.

First, you need to decide whether you prefer .*/ or .*/index.html. I'm in for the former, because I wanted to have a coherent scheme with directory listings, too, and it doesn't make sense to have a webserver-generated directory listing at the location of a file. Also, it seems to me like it's the more semantically correct url. My requirement was to have the forward for all directories and index.html files, not only for the top level /index.html. The usual examples don't cover that and / or use two regexes, but I found an easy way to do it with a single one.


For nginx, you need the rewrite directive and a small workaround:

# forward all index.html files to their parent directories for having unique urls
rewrite ^(.*/)index.html$ $1 permanent;

# The default index directive, "index index.html;", reacts on .*/
# with an internal redirect to .*/index.html, which is then affected
# by the rewrite, resulting in an infinite redirect loop.
# This location directive breaks the loop by bypassing the index directive
# and directly trying to serve index.html.
location ~ ^(.*)/$ {
    try_files $1/index.html =404;

The index index.html directive works with an internal redirect, which seems to get caught in the rewrite rule again, endlessly. try_files also does an internal redirect like the index directive, but as it's enclosed in a location block, it doesn't reach the rewrite above anymore (At least I think that's the reason… drop me an email if you know more about or a better way to do this).


For Apache, you need the RewriteRule directive:

RewriteEngine on
# forward all index.html files to their parent directories for having unique urls
RewriteRule ^(.*/)index\.html$ $1 [redirect=301,last]

No workaround needed for apache, the rule just works as expected. But don't forget a

sudo a2enmod rewrite

if you don't have mod_rewrite already enabled.

Have fun!

Remarks? Additions? Corrections? For anything you want to tell me about this blog post, feel free to send me an email.
Despite having no comments section (isn't that easy with a static site generator and without relying on a proprietary 3rd party service), I greatly appreciate direct feedback. ;) In case of additions, I'll mention the name from the mail if you don't object.