Transfering mod_rewrite rules from htaccess to nginx

I am trying to convert some already working rewrite rules from .htaccess to nginx.
My application has 2 modes, backend (all calls starting with /admin/*) and frontend, the rest of the calls. Backend requests get routed to admin.php while frontend ones get routed to index.php

This works great in apache but in nginx I can only get the frontend routing to work. The /admin/ requests do call the admin.php file but the php file is downloaded instead of being executed. I’ve already used to convert my htaccess routes to nginx but I still can’t get it to work for /admin.

Can an nginx pro help me out with the proper config to do this?

This is my working .htaccess config:

<IfModule mod_rewrite.c>
#RewriteBase /

# Google sitemap.xml configuration
RewriteRule sitemap.xml$ /index.php?_extension=Frontend&_controller=Sitemap&action=googleSitemap [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+).(d+).(php|js|css|png|jpg|gif|gzip)$ $1.$3 [L]

# admin routes
RewriteRule ^/admin/(.*)$ admin.php?%{QUERY_STRING} [L]

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

# frontend routes
RewriteRule .* index.php [L]


and this is the nginx configuration that I tried so far…

server {
    listen       80;
    server_name  mydomain.local;
    root   /var/www/project;
    index  index.php index.html index.htm;
    access_log  /var/log/nginx/default-access.log  main;
    error_log   /var/log/nginx/default-error.log;

    error_page   500 502 503 504  /50x.html;

    location = /50x.html {
        root   /var/www/default;

    location / {
        rewrite sitemap.xml$ /index.php?_extension=Frontend&_controller=Sitemap&action=googleSitemap redirect;
        try_files $uri $uri/ @rewrite;
    location @rewrite {
        rewrite ^(.*)$ /index.php;
    location /admin {
        rewrite ^/admin/(.*)$ /admin.php?$query_string break;

    location ~ .php {
        include                  fastcgi_params;
        fastcgi_keep_conn on;
        fastcgi_index            index.php;
        fastcgi_split_path_info  ^(.+.php)(/.+)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors on;
        fastcgi_pass unix:/var/run/php-fpm.sock;

with nginx on, doing a curl -s -D – ‘http://mydomain.local/frontend/call‘ | head -n 20 does return the Content-type as text/html while a call to curl -s -D – ‘‘ | head -n 20 returns the application/octet-stream content type which triggers the download.

Source: stackoverflow-php