Nginx – Correct rewrite syntax to remove index.php

magentonginxrewrite

I got an nginx vHost that hosts:

  • a CMS in /
  • a magento shop in /store

Things are running fine except one thing:

Removing index.php from the URL. At the moment the following URLs are working

example.com/store/index.php/my-funny-test-product.html and (as there are a few subshops in magento) 
example.com/store/index.php/city/my-funny-test-product.html

Now I have to build a redirect so that the index.php can be stripped off the URL.

example.com/store/my-funny-test-product.html or example.com/store/city/my-funny-test-product.html

I got it to work on my local Apache with this .htaccess

RewriteEngine on
RewriteBase /store/

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule .* index.php [L]

Based on this I built the following rewrite

location /store {
   rewrite ^/store /store/index.php;
}

Now example.com/store/my-funny-test-product.html works but CSS images and the like are broken!
I tried adding if (!-e $request_filename) to fix that but then got an nginx 40x error.

How can I achieve a working rewrite of example.com/store/my-funny-test-product.html and example.com/store/city/my-funny-test-product.html to the subfolder /store without breaking css & co and without having index.php in the URL?

Here's the full vhost config

    ## The whole setup stays close with the magento recommendations
    ## http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/configuring_nginx_for_magento

server {
    listen myip:80;
    server_name .example.com;

    root /var/www/mydomain/public_html;

    location / {
        index index.html index.php;
        try_files $uri $uri/ @handler;  
    }

    ## here comes my rewrite stuff to remove index.php from the subfolder ##
   location /store {
       rewrite ^/store /store/index.php;
   }

    ## followed by some deny rulesets not relevant here ##

    location @handler { ## Magento common front handler
        rewrite / /index.php;
    }

    location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
        rewrite ^(.*.php)/ $1 last;
    }

    location ~ .php$ { ## Execute PHP scripts
        if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss

        expires        off; ## Do not cache dynamic content
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  HTTPS $fastcgi_https;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  MAGE_RUN_CODE default; ## Store code is defined in administration > Configuration > Manage Stores
        fastcgi_param  MAGE_RUN_TYPE store;
        include        fastcgi_params; ## See /etc/nginx/fastcgi_params
    }

Best Answer

Now example.com/store/my-funny-test-product.html works but CSS images and the like are broken!

Use try files

Requests for css files (or, any actual files in /var/www/example.com/public_html/store) aren't working at the moment because the requeset is routed unconditionally to /store/index.php. The minimal change necessary to make that work - is to use try_files:

## here comes my rewrite stuff to remove index.php from the subfolder ##
location /store {
    # rewrite ^/store /store/index.php; NO
    try_files $uri /store/index.php;
}

In this way, if the following file exists:

/var/www/example.com/public_html/store/css/style.css

Then the following url will return its content:

http://example.com/store/css/style.css

And any request starting with /store that does not directly map to a file will be passed to /store/index.php.