Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Corez64's avatar

nginx alias and rewrites

I am trying to get a legacy project I'm developing running in Homestead but I'm not familiar enough with nginx to get it working right. I know I can get this working in Apache with the following Alias:

Alias /path/to/project/api/public
<Directory /path/to/project/api/public>
    Order allow,deny
    Allow from all

    # Rewrite
    RewriteEngine On
    RewriteBase /api
    RewriteRule . index.php
</Directory>

I have succeed in getting the alias to mount correctly but I haven't managed to get the paths to write to the index.php file so /api/ gives me what I am expecting but /api/users gives a 404. When I tried adding something like rewite ^/api/(.*) /api/index.php?$1 break; I will get a 500 error and the log has

rewrite or internal redirection cycle while processing "/api/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/users", client: 192.168.10.1, server: project.local, request: "GET /api/users HTTP/1.1", host: "project.local"
"alias" cannot be used in location "/api/" where URI was rewritten, client: 192.168.10.1, server: project.local, request: "GET /api/ HTTP/1.1", host: "project.local"
server {
    listen 80;
    listen 443 ssl;
    server_name project.local;
    root "/home/vagrant/Code/project/public";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location /api/ {
        alias "/home/vagrant/Code/project/api/public/";
    }

    location ~ ^/api/(.+\.php)$ {
        alias "/home/vagrant/Code/project/api/public/";

        fastcgi_param SCRIPT_FILENAME $document_root$1;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
    }
}
0 likes
13 replies
bashy's avatar

I believe you will want something like this. Haven't tested but you should be able to trial and error :)

location /api/ {
    alias /home/vagrant/Code/project/api/public/;
    try_files $uri $uri/ /index.php?$query_string;
}

// or if above fails
location ~ ^/api/(.*)$ {
    alias /home/vagrant/Code/project/api/public/;
    try_files $uri $uri/ /index.php?$query_string;
}
Corez64's avatar

Thanks for the suggestions @bashy both version you suggested gives me "No input file specified" in the browser and the following error in the log:

FastCGI sent in stderr: "Unable to open primary script: /home/vagrant/Code/project/public/index.php (No such file or directory)" while reading response header from upstream, client: 192.168.10.1, server: project.local, request: "GET /webservices/provider/instructions/PersonalInjury HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "project.local"

I also tried try_files $uri $uri/ /api/index.php?$query_string; which produced the following error in the log:

astCGI sent in stderr: "Access to the script '/home/vagrant/Code/project/api/public/' has been denied (see security.limit_extensions)" while reading response header from upstream, client: 192.168.10.1, server: project.local, request: "GET /api/provider/instructions/PersonalInjury HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "project.local"
bashy's avatar

Weird how it's missing out the api folder... tried without trailing slash on the location parts? location /api { }

Maybe

location /api {
    try_files $uri $uri/ @api;
}

location @api {
    // some type of rewrite/alias
}

Other than that, does your api app work from /api/users or just /users? (Route file)

Corez64's avatar

@bashy unfortunately there is no route file as this project predates Laravel (and most PHP development standards for that matter) I'm just trying to get it to run in homestead. Perhaps if I explain a little about my reasoning for this you might be able to point me in a better direction.

I have my main application where all the file are inside the web root (old school style) so the domain maps strait to the project file (/code/project/ maps to project.local). There is also a separate codebase which handles the SOAP API which has a more modern project structure with a public folder which I need to map to project.local/api and anything after that needs to get routed to the index.php e.g project.local/api/soap/service/name will get mapped to /code/project_api/public/index.php?soap/service/name.

bashy's avatar

Yeah that's what I was thinking. I'm not too sure (and never had to) on how to rewrite a URI segment to another folder while removing one part and all via index.php. If I find any more info I'll post it here.

Erulezz's avatar

I had the same problems a few weeks ago also with an Alias and the error message No input file specified. Turns out you need to place the PHP-FPM config (fastcgi config lines) also in your new location block. That worked for me!

bashy's avatar

@keypoint Think you need to put the PHP stuff inside the location block so it passes it to PHP for that URL.

keypoint's avatar

Which ones?

My 2 location blocks look like this:

set $kps_quiz_root /srv/users/serverpilot/apps/...;
location /quiz {
    alias $kps_quiz_root;
    index index.php index.html;
    try_files $uri $uri/ /index.php$is_args$args;

    location ~ \.php$ {
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:17200;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

location / {
    autoindex off;
    index index.php index.html;
    try_files $uri $uri/ /index.php$is_args$args;

    location ~ \.php$ {
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:17200;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

@bashy The thing is, the error I'm getting (Unable to open primary script) refers to an existing index.php file (the path is valid). Yet, it reports no such file or directory. Maybe it's a serverpilot permissions issue, because on my local vagrant it worked without issues... Yeah, in fact this is the issue - the same config works on my dev machine (different root, that's all)

keypoint's avatar
Level 4

No shame in admitting that sometimes I get to overthink things. It took one of the guys at serverpilot to enlighten me: @Corez64, if you still have the issue, here is a clean fix: define another vhost for your inner app, then simply symlink its public dir to a name in your first vhost's public dir. It will work and it keeps the 2 configs separate, as they are in fact (in my case at least), different apps.

1 like
bashy's avatar

@keypoint Yeah I haven't tested doing a sub dir site much. The problem with the main thread version is the two apps being in the same set of files so can't really symlink it :/ I would suggest symlink normally and I would of for you but I thought you had the same issue!

keypoint's avatar

In my case one domain's app was inside another's base folder. Symlinking did the trick, in this case. It would still be interesting to know how to do it by solving the config issue, but I'll leave that for another time. Thanks!

Please or to participate in this conversation.