nginx Subdirectory Rewrites for MVC

Peter asked:

I am tasked with administering a web application that has a base directory with a bunch of legacy code in it, and a subdirectory of my own making with an MVC based API which we are using to slowly migrate the front end to a SPA model. The owner has gotten a wild hare up his ass and decreed that we are to move to nginx.

I have extensive experience in Apache rewrites, and it would take me about nine seconds to set this up in Apache. However, as people are quick to point out, nginx is not Apache. While I can get either section of the application to work on its own in nginx, I cannot get the API to play nice with the main application when it is in its /api/ directory.

I’m guessing that it will be some permutation of the location directive, which appears to behave similarly to in Apache. Basically, if anything hits the /api/ directory, I need to pass the remainder of the uri to /api/public/index.php with the rewrite:

^/(.*)$ public/index.php?_url=/$1;

Any help is greatly appreciated.

Existing config:

 server {
            listen ssl;
            ssl_certificate /etc/nginx/conf.d/chain.crt;
            ssl_certificate_key /etc/nginx/conf.d/4096_SSL.key;
            set $root_path '/usr/share/nginx/www';
            root $root_path/trunk;
            index index.php index.html;
            fastcgi_param ENV development;
            fastcgi_buffers 8 16k;
            fastcgi_buffer_size 32k;
            fastcgi_read_timeout 180;
            location / {
                    try_files $uri $uri/ =404;

            location ^~ /api {
                    rewrite ^/(.*)$ public/index.php?_url=/$1;

            fastcgi_intercept_errors off;

            location ~ \.php {
                    fastcgi_pass   unix:/var/run/php-fpm.sock;
                    fastcgi_split_path_info ^(.+\.php)(.*)$;
                    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                    include        fastcgi_params;

This config is ugly because I’ve been playing with it all day, but it should get the point across.

My answer:

You’re right that nginx isn’t apache, and that means that most of the places you might think of using rewrite, are inappropriate. Instead you should try to use try_files. For instance:

location /api/ {
    try_files $uri /api/public/index.php?_url=$request_uri;

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.