Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top


I have a website with the following structure:


I would have liked to make the URL's cleaner, so I would be the equivalent structure with:

/ => /index.html
/about/ => /about/index.html
/contact/ => /contact/index.html
/contact/send_email.php => /contact/send_email.php

Basically an Nginx configuration that removes all index.html or index.php file names from the URI.

My Attempted Configuration

server {
    listen 80;
    root /home/www/mysite;

    location ^~* /[a-z]+/index\.(html|php)$ {
        rewrite ^(/[a-z]+/)index\.(html|php)$$1? permanent;

    try_files $uri $uriindex.html $uriindex.php =404;

    location ~ \.php$ {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass unix:/var/run/php5.sock
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

The Problem

In short - it doesn't work. When I go to /about/index.html it should permanently redirect to /about/ but it just stays on /about/index.html. I have tested the regular expressions and they seem to be fine - i.e. the capturing group defined in the rewrite works.

share|improve this question
up vote 1 down vote accepted

Which version of nginx are you using?

I've tried your configuration with nginx 1.4.2 and it detected a few syntax errors:

  1. invalid location modifier "^~*" in your first location directive - I changed it to ~
  2. unknown "uriindex" variable in your try_files directive - I changed both $uriindex.html and $uriindex.php to $uri/index.html and $uri/index.php

At this point I believe the setup does most of what you want:

  1. Going to you're redirected to
  2. Going to you're redirected to
  3. Going to no redirect takes place

Now for to redirect to, you'll need another "location" directive and rewrite rule:

location ~ /index\.html$ {
    rewrite ^/index\.html$ permanent;

And as for to be executed with PHP-FPM as script, you'll also need a specific location directive. The fastcgi_index index.php line here is really important:

location = /contact/ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/run/php5.sock
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Hope this helps :)

share|improve this answer
Thanks for the changes. I am running nginx version 1.1.19. My only problem now is when I try to go to /contact/index.php it downloads the PHP page instead of running it through PHP-FPM. The location ~\.php$ block doesn't seem to catch the $uri/index.php directive in try_files. – Hzmy Sep 17 '13 at 15:07
location ~\.php$ doesn't catch /contact/index.php because its rewritten to /contact/. You need one more location directive, I've updated the answer above to show this. – zygis Sep 17 '13 at 16:24
I thought about doing this originally, but I would have to add a new location =/xxxx/ block for any directory with an index.php. – Hzmy Sep 18 '13 at 14:44

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.