Nginx rewrite root to sub-folder without changing server root

Solution 1:

Resetting your document root back to the top. Try this:

location / {
    try_files $uri $uri/ @public;
}
location @public {
    rewrite ^ /public$request_uri last;
}
location /public {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/(.*)$ /public/index.php?url=$1 last;
}

The first and second location blocks will serve the back-end files and ensure that anything else gets rewritten to the /public folder (your first .htaccess rule set).

The third and fourth location blocks will serve files from the public folder (if they exist) and otherwise invoke the /public/index.php script.

I presume that you already have a PHP location block.

The above may be overkill (I am just following your Apache implementation), and this may also work (skipping a few steps):

location / {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/(.*)$ /public/index.php?url=$1 last;
}

If you don't mind a leading slash in the url parameter, it can be simplified to:

location / {
    try_files $uri $uri/ /public/index.php?url=$uri;
}

See this and this for more.